【自用】POJ1064 Cable master 且来说说卡精度的心得

广告:

#include <stdio.h>
int main()
{
    puts("转载请注明出处[vmurder]谢谢");
    puts("网址:blog.csdn.net/vmurder/article/details/44347241");
}

题意:

多组数据,n个小棒,分成m段,最长多长?
不能短于0.01,如果分不出来,输出”0.00”

题解:

满足单调性,来二分吧。

心得:

来,我们看着代码说话。

判无解的处理

首先最多能分多少段开了long long。
long long maxd,m;
然后处理的时候因为精度损失,所以加了eps
maxd+=(int)(a[i]*100.0+eps);

eps

因为处理两位,所以至少应该开4位吧,然后因为其它的一些东西,所以我最终开了八位
#define eps 1e-8

避免出现无解而误判的情况

右边界的设置减了eps,事实上这里并不需要进行此项判断。
double l=0.01,r=mx-eps,mid;

对于答案的输出

我们发现因为精度损失,所以导致末尾舍去的时候会出现误差,这个时候应该灵活的减去或者增加 2
printf("%.2lf\n",l-0.00499);
啊这里有点瞎了,貌似应该是+0.005,但是过了。

至于为什么是0.00499呢?因为还有精度损失,所以还需要加减eps。

选择语言

正规考试并不会有这个问题,但是平时评测的时候,尤其POJ!
每改一份代码,你可能需要C++和G++都交一遍。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 10100
#define eps 1e-8
using namespace std;

int n;
long long maxd,m;
double a[N],mx;
bool check(double mid)
{
    int ret=0,i;
    for(i=1;i<=n;i++)ret+=(int)(a[i]/mid+eps);
    return ret>=m;
}
int main()
{
// freopen("test.in","r",stdin);
    int i,j,k;
    while(scanf("%d%I64d",&n,&m)!=EOF)
    {
        maxd=0,mx=0.0; 
        for(i=1;i<=n;i++)
        {
            scanf("%lf",&a[i]);
            mx=max(mx,a[i]);
            maxd+=(int)(a[i]*100.0+eps);
        }
        if(maxd<m)
        {
            puts("0.00");
            continue;
        }
        double l=0.01,r=mx-eps,mid;
        while(r-l>eps)
        {
            mid=(l+r)/2.0;
            if(check(mid))l=mid;
            else r=mid;
        }
        printf("%.2lf\n",l-0.00499);
    }
    return 0;
}

你可能感兴趣的:(二分查找,二分,卡精度,自用,poj1064)