poj 3232 和 3104:二分逼近

3232 Accelerator(二分逼近)
二分法的总体思路就是,(1)以二分的方法确定一个值,假定这个值就是答案,(2)判断这个值是大还是小,并在相应半区重新估值,再判断;(3)以半区区间的左边界left不再比右边界小为结束条件。(有一点贪心的思路在里面,这个最短的时间内,显然所有加速器都在被使用,这样才会时间最短)(这就要求,要事先知道判断方法:一个值是偏大还是偏小,如果知道了判断方法,就能逼近最优解:先随便找一个解,然后判断,然后二分再判断)

题意:给出n辆赛车距离终点的距离,每秒钟会前进1米,现在给出m个可以加速k的加速器,每次每辆车只能使用一次加速器,下一个时间点加速器可以重复使用。问所有赛车到达终点的最短时间。
输入:
(1)T,小面有T个case;
(2)N,有N个赛车;
(3)N个数,表示赛车到终点的距离;
(4)M,K,表示有M个加速器,及加速度;
输出:
T行数:每个案例全部赛车到达终点的距离。
与3104题意相同,只是由一个吹风机变成M个吹风机。小雨3104超时,看这次能否重新理解和完成。
思路:
(一)简单的贪心思路,如吹风机每一分钟都选择最湿的衣服烘干,加速也在每分钟都选择距离最远的M个赛车加速就可以了。这就意味着,每一分钟要对赛车到终点的距离排序。但是看数据,肯定不能去模拟每一分钟(对每一分钟进行排序会超时,如同小雨做3104时的情况)。既然不能模拟每一分钟,也就意味着不需要给最大的加速。
(二)二分逼近
本题步骤:
1、要找所有车全部通过终点的最短时间,显然,这个时间在1和最远距离max之间。于是,通过二分法,假定mid就是这个最短时间,然后去判断(check函数)这个时间是大了还是小了,再在某一半区重新二分得到mid,一直到l=r(区间最小),得到正确答案。
2、如何判断,即写一个函数:int check(int acc_time),在主程序中调用是为check(mid),也就是把mid作为加速的时间(就是加几次速),判断大了还是小了
(1)函数目的是,判断给定的acc_time作为赛车都过终点的最短时间,是大了还是小了。
(2)显然,要对每台车进行分析
(3)如果本车离终点的距离小于等于mid,显然,它不用加速,自己就走过去了,于是进入下一台车的判断。
(4)否则,意味着这台车需要加速,于是要计算这台赛车需要加速的次数times。本题关键就在于:对本台车的加速次数如何计算?
本台车,距离终点a[i],可以这么看,所有车到终点的预设时间是mid,在这mid分钟内,设加速times次,那么a[i] =times×k + (mid –times),前一个是加速走的距离,后面是自己走的距离,于是,times = (a[i] – mid)/(k-1),注意向上取整。
(5)判断:
Mid偏小有两个判断,一是看单台车,二是看总加速次数:
如果本车的times大于mid(也就是总体上给的赛车只能加速mid次),就意味着,这台车要到终点,需要加速的次数比给的mid要大,所以,mid预估小了,返回false。一旦发现有一辆车是这种情况,就不再往下check了,返回false,之后在主程序中调大m的值;
还有一种估值小的可能,就是所有车的总加速次数,在循环中累加每台车的加速次数,如果大于mid*m(即有m台加速器,就是假定到终点的时间为mid,那么,所有车可以加速的总次数是m×mid),也说明mid估计小了。所有车的加速总次数用累加,就是把本台车的加速次数tmp累加上去。
偏大的判断:
在对所有车都分析一次后,如果没有返回false,就说明mid的估值不小(可能大了),返回true。然后,在主程序中缩小估值,再判断。
至此,这道题就分析完成了。

AC细节:

  1. ceil函数加上 1.0*,从整数变成浮点数乘法;times = ceil(1.0 * (a[i] - mid) / (k - 1));
  2. long long total= (long long) m * acc_time; //一定要注意!int溢出是随时都可能发生的,所以先强制转换,保存起来
  3. 二分法循环条件用小于等于while(left <= right)
  4. 处理k=1的特殊情况,如果k=1,直接输出最大值max
  5. 超时处理:用scanf\printf替代cin\cout;
  6. Wrong answer:二分输出left而不是mid;需要试验一下,一般mid也对。

3104与3232相似:加速器台数m只在函数check(mid)中判断总加速次数是否超过m×acc_time时用到,在只有一个加速器(烘干机)时,这个条件可以去掉,然后,就可以成为3104的解决方案。

3104题意:有n件刚洗的衣服,每件衣服给定一个含水量。有一个烘干机,每分钟可以选一件衣服去烘,每分钟可以烘掉k的水量。每件衣服每分钟可以自动蒸发掉1的水量,用烘干机时不蒸发。问最少需要多少时间能烘干所有的衣服。
输入:
第一行:n,表示n件衣服;
第二行:n个数,表示n件衣服的含水量;
第三行:k,表示烘干机每分钟去掉的水量。
输出:
多少分钟把n件衣服烘干。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值