我的二进制搜索应用程序不在这里吗?

时间:2015-11-01 10:30:55

标签: c++ algorithm binary-search

所以,我正在解决这个问题:http://www.spoj.com/problems/IMMERSED/

  

一项奇妙的发现即将在生物学领域发生,您也是研究团队的一员。该研究涉及在无氧环境和有毒物质存在的环境中测量细胞生长。该团队得出了一个愚蠢的假设,分析的数据告诉他们:增长,天数和毒性;与此公式有关:

     

P = N * N cN ;

     

其中 P 是在数千个细胞中测量的增长。

     

N 是经过的天数。

     

c 是与实验毒性水平相关的常数。

     

当这些细胞达到特定的生长时,您的生物合作伙伴需要从细胞中取出一些组织。考虑到毒性水平和所需的增长,他们要求你编写一个程序,告诉他们确切的时间。

     

输入

     

第一行是 T (1≤ T ≤40,000),测试用例的数量,然后是 T 测试用例。< / p>      

每个测试用例是一个由空格分隔的2个整数( P c )的行。

     

P (1≤ P ≤10 15

     

c (1≤ c ≤5)

     

输出

     

对于每个测试用例,您必须以十进制格式输出预期时间。

我所做的是使用二元搜索来查找天数如下:

#define eps 1e-7
const double cont = 14.0;
double p,c;
double binary (double start, double end);
double func (double n);
int main (void)
{
    int t;
    cin>>t;
    while (t != 0)
    {
        cin>>p>>c;
        double mid,ans,start=0,end=cont;
        ans = binary(start,end);
        cout.precision(6);
        cout<<fixed<<ans<<"\n";         
        t--;
    }
    return 0;
}

double func (double n)
{
    double ret = n*pow(n,c*n);
    return ret;
}

double binary (double start, double end)
{
    if (start <= end)
    {
        double mid = start + (end-start)/2.0;
        if (func(mid)-p <= eps)
            return mid;
        else if (func(mid)-p > eps)
            return binary(start,mid);
        else
            return binary(mid,end);
    }
}

但是,在运行我的代码时,即使是给定的测试用例,它也会给出错误的答案:

Input:
3
1 1
3 4
100 1
Output:
1.000000
1.207384
3.086308

My output (for the above input)

0.875
0.875
1.75

PS:我没有发布库,所有这些都是为了避免混乱。另外,一旦得到正确的值,我会将其设置为6位小数。我只是想知道,我的逻辑是不正确还是我的二进制搜索执行不正确?

编辑:我提交的新代码

double binary (double start, double end)
    {
        if (start <= end)
        {
            double mid = start + (end-start)/2.0;
            double delta = func(mid) - p;
            if (delta < -1*eps)
                return binary(mid,end);
            else if (delta > eps)
                return binary(start,mid);
            else
                return mid;
        }
    }

2 个答案:

答案 0 :(得分:4)

您正在以不健全的顺序进行测试:

if (func(mid)-p <= eps)
    return mid;
else if (func(mid)-p > eps)
    return binary(start,mid);
else
    return binary(mid,end);

尝试

if (func(mid)-p < -eps)
    return binary(mid,end);
else if (func(mid)-p > eps)
    return binary(start,mid);
else
    return mid;

我也不确定这两个递归调用。在这种情况下,我保留了你的逻辑(因为我可能误解了你的公式),但他们向后看我。

我确信你应该在内部案例之前测试(并使用递归调用)两个外部案例(func(mid)-p < -epsfunc(mid)-p > eps)(然后有效{ {1}})

编辑:该二进制搜索的更清晰(更快)版本是:

abs(func(mid)-p) < eps

牛顿搜索可能比这更快。

答案 1 :(得分:2)

除了搜索JSF解释的问题之外,您还可以比您需要的更准确地计算方式。

您需要N,精确度为10 ^ -6。通过实施,您可以进行搜索,直到找到具有P的值,精确度为10 ^ -7。由于函数是指数的,因此非常陡峭,即PN的变化非常快,这将导致计算量超出必要的程度。

相反,你应该有一个停止条件end - start < 1e-6

现在我有一个语义问题:10 ^ -6的准确度是否意味着所有数字必须正确,或者最后一个数字是否允许关闭1?如果允许,startend在停止后将是一个很好的答案。如果没有,你可以将它们向上舍入到最接近的10 ^ -6。你应该四舍五入,因为该陈述可能要求第一个N func(N) > P,而不是相等的近似值。然后,如果它们不同,请检查start的舍入值是否满足该语句。如果是,则输出,如果不是,则输出舍入值end

给定14.0的上限,搜索空间只是14.0 / 1e-6 = 1.4 * 10^8个元素。它的基数2对数刚好超过27,因此每个测试用例应该只需要28次迭代(如果计算更准确的上限,则可能需要27次)。这绝对不应该要求复杂的优化。