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

Is my application of binary search not right here?

本文关键字:在这里 应用程序 搜索 二进制 我的      更新时间:2023-10-16

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

一个奇妙的发现即将在生物学领域发生,而你是进行研究的团队的一员。这项研究是关于测量细胞在无氧气和有毒物质存在的环境中的生长。研究小组得出了一个恶毒的假设,分析数据告诉他们:生长、天数和毒性;与以下公式相关:

p=N*NcN

其中p是在数千个细胞中测量的生长。

N是经过的天数。

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

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

输入

第一行是T(1≤T≤40000),测试用例的数量,然后是T

每个测试用例都是一行,其中有2个整数(Pc),用空格分隔。

p(1≤p≤1015

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

附言:我没有张贴图书馆和所有为了避免混乱。此外,一旦得到正确的值,我会将其设置为小数点后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;
        }
    }

您的测试顺序不合理:

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;

我也不确定这两个递归调用。我保留了你的逻辑(因为我可能误解了你的公式),但他们回头看我

我确信的是,您应该在内部案例(实际上是abs(func(mid)-p) < eps)之前测试(并使用递归调用)两个外部案例(func(mid)-p < -epsfunc(mid)-p > eps

编辑:更干净(更快)的二进制搜索版本是:

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

牛顿搜索可能比这更快。

除了解释搜索JSF的问题外,您还可以更准确地计算方法

您需要精度为10^-6的N。对于您的实现,您一直在搜索,直到找到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次)。这绝对不需要复杂的优化才能通过。