Cable master(POJ1064)

题目链接:http://poj.org/problem?id=1064

题目大意:就是有N个不定长度的绳,然后有我们现在需要K个相同长度绳,从这N个已有的绳上截取,问所能截取的最大长度是多大。

这个会卡精度,所以我错了好多次,开始的时候我还以为是直接取整,然后交了就错了,后来再改,发现是区间定的是1-MAX,肯定错啊,再改,begin_是mid+1,这也肯定错,因为是有小数的。然后我开始的时候while()的条件写的是begin_<end_这也不对,就跑不完了,死循环。改完这些之后,然后mid新加了一个*100/100以求去后取前防止进位,然而还是不对,这就很尴尬了是不是,嗯好像是吧,又好像没有。最后把mid改成了end_然后就很神奇的过了……………………………………………………………………………………………………………………………………………………………………,我也很无语,而且我不知道为什么,求解ing QAQ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^

等一下,大于等于的时候取右,小于的时候取左,所以这个区间应该是左闭右开
但是这个是浮点型的数据,所以好像又和这没啥关系,
之所以取右端点,是因为那个点是刚好达到成功点之前的那个大于的状态(因为那个啥,因为那个本来区间长度就很小,小于了1e-8),但是*100以后再/100就是向下取整,也就是去掉了三位小数之后的小数,但是mid就是有偶然性,由于左右区间的选择,所以mid肯定不对,但是那个begin也是不对的吧,万一就在1.00左右,那就很尴尬呀,所以应该是这样吧,我也不知道,以后有了想法再加嘛……吃饭了,天那,我还是没有去吃饭,我的快递还没拿,哭了……

#include<stdio.h>
#include<string.h>
#include<algorithm>
#define FMAX 1e4
#define dif 1e-8
using namespace std;
int N,K;
double L[10005];
bool judge(double m)
{
    int sum=0;
    for(int i=0; i<N; i++)
    {
        sum+=(int)(L[i]/m);
    }
    return sum>=K;//这儿呢,我开始就写的>,wa!因为我们要找的是最大值,所以肯定要取后区间,所以呢,要大于等于,不信可以调试一下哈,出来的结果是比较小的
}
int main()
{
    while(~scanf("%d%d",&N,&K))
    {
//        double summ=0;
        double MAX=0;
        for(int i=0; i<N; i++)
        {
            scanf("%lf",&L[i]);
            if(MAX<L[i])//这儿本来不想弄这玩意,因为二分时间复杂度又不高,所以直接定义了一个区间,但是竟然T了一次……当时别提我多激动了,改了这就对了吧我就想!结果还是wa!emmm……
                MAX=L[i];
//            summ+=L[i]*100;
        }
//        if(summ<K)//这个是我开始为了过那个0.00的案例加的,后面其实改了后面之后,这儿要不要就无所谓了
//        {
//            printf("0.00\n");
//            continue;
//        }
        double begin_=0,end_=MAX,mid;
        while(end_-begin_>=dif)
        {
            mid=(begin_+end_)/2;
            if(judge(mid))
            {
                begin_=mid;
            }
            else
            {
                end_=mid;
            }
        }
        end_=((int)(end_*100))/100.00;
        printf("%.2f\n",end_);
    }
    return 0;
}

几组样例:

3 5
1.02
3.14
4.60
ans=1.53

4 2540
8.02
7.43
4.57
5.39
ans=0.01

4 2542
8.02
7.43
4.57
5.39
ans=0.00

4 11
8.02
7.43
4.57
5.39
ans=2.00

又重新对这道题有了点点的想法,然后补一下:
为什么最后是输出end_?

先说一下浮点数相等的问题:
计算机中存储数据是以二进制存储,所以浮点数会有一定的精度,如果不能刚好被二进制存储,就要近似存储。
浮点数如何比较?
学过数学物理都知道现实问题中是会有一定的误差的,所以这个浮点数也是近似相等。假设有两个浮点数a,b,我们如果判断它们是否相等?:
假设要求的精度是1e-8
那么只要fabs(a-b)<1e-10,(或者比1e-10更小的一个极小数),就可以近似a和b相等

然后再说我们这道题:
之所以是输出end_,和上面所说的这个近似是有一定关系的,我们的judge里面的sum是取整的,所以我们舍去的那一段绳子可能刚好与mid近似,所以我们得到的值是不精确的,换句话说是偏小的。所以我们要取右端点,因为左右端点相差1e-8,也可以是近似相等了,但是就是由于前面的原因,我们要取右端点,以防误差。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值