POJ - 1064 Cable master(二分法无限逼近)

本文介绍了一种利用二分法逼近求解最优值的方法,通过调整左右边界逐步缩小解的范围,最终找到满足条件的最大值。并详细解析了判别函数中条件选择的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大致思路为先自定义left,right的值,然后使用二分法得到mid,测试mid是大于要求的值还是小于要求的值,然后最终使left 与right无限逼近答案。

#include <cstdio>
#include <cmath>
using namespace std;
const double inf = 200005;
double num[10005];
int N,T;
bool  pan(double x)
{
	int sum = 0;
	for(int i = 1;i<= N;i++)
		sum += (int)(num[i]/x);
	return sum>=T;
}
int main()
{
	while(~scanf("%d%d",&N,&T))
	{
		for(int i = 1;i<=N ;i++)
			scanf("%lf",&num[i]);
			
		double ri = inf,le = 0;	
		
		while(ri-le>1e-9)//for(int i=1;i<=100;i++)
		{
			double mid = (ri+le)/2;
			if(pan(mid))
				le = mid;
			else 
				ri = mid;
		}
		printf("%.2f\n",floor(ri*100)/100);//此处的for可以使用le
		 /*题目要求求最大值故用ri ,但当精度非常大时,ri与le是几乎相同 
		 并且答案要求保留小数点后两位,故ri与le 都可以,
		 在这个中,while与for达到相同精度while所循环次数大于for,会出问题,
		 所以建议使用for,i<=100足以精确到小数点后30位. */ 
	}
	return 0;
}

对于pan函数中为什么是sum>=T,而不是sum>T 我在这里解释一下:

首先 sum的值象征着什么?
从代码中我们可以看到sum是由 (int)(num[i]/x)的结果不断累加产生的,故sum的结果越大,说明x越小,注意这里用到了强制转换。所以sum是将多出的小数毛刺去掉了再累加的结果。

其次 如果这个sum计算出的结果是等于sum的,那我们应该将此时的x放到左,还是右?
尽管是sum是等于 T的,但不要忘记,此时的sum只是去掉小数毛刺后的累加值
所以说实际的sum(不强转(int)去掉毛刺的情况下)可能是要比T大的。说明x实际上是可能比正确答案要小的。所以我们将其放到左侧 而不是右侧。

添加一行代码来测试:

for(int i=1;i<=100;i++)
        {
            double mid = (ri+le)/2;
            if(pan(mid))
                le = mid;
            else 
                ri = mid;
             //添加的测试数据代码
            printf("行号:%d  le = %.2f  mid = %.2f  ri = %.2f\n",i,floor(le*100)/100,floor(mid*100)/100,floor(ri*100)/100);
        }

两次如图:左侧(sum>T) 右侧(sum>=T)
在这里插入图片描述
左图的数据是sum等于T的时候 将x放到右侧(sum > T)
右图的数据是sum等于T的时候 将x放到左侧(sum >= T)

我们可以发现17行及其之前的数据是相同的,但是在第18行出现了不同,
左图将0.76放到了右侧(ri = mid)
右图将0.76放到了左侧(le = mid)

实际的sum(不强转(int)去掉小数毛刺的情况下)可能是要比T大的。说明x实际上是可能比正确答案要小的。所以应当le = mid,代码写为 sum >= T。(如右图)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值