2013寒假练习 1005:穿越沙漠
2013-02-01 14:34
260 查看
地址:http://acm.bit.edu.cn/mod/programming/view.php?id=656
趣题,所以把题面也搬过来
比较数学化的推理参看/article/10284949.html
比较形象化的解释:
x<=500 那么无须在中途扔油,耗油量就等于x,在边界x=500处,耗油500;
500<x<=500+500/3 此时为了最后一次能跑完超过500的距离,必须在终点前500距离扔油(*),如图所示。那么总共所需油为3a+500 也就是在这一阶段,每增加1公里路程,需要多用3升油(2升用来往返扔油,1升是多走1公里所用的油)。但是当a这一段多出来的距离大于500/3时,3a>500,也就是从起点去扔油的所需的油都已经超过了500,那么就需要再多扔一次油。所以边界条件为X=500+500/3时,此时耗油1000.
500+500/3<x<=500+500/3+500/5 此时需要扔两次油,位置如图。为何第一个点要扔3a呢?因为接下来第二次扔油的一个来回多走了2a,最后穿过沙漠的那一次多走了a,所以要扔3a的油。此时耗油为5a+1000,即每增加1公里路程,需要多用5升油。当a大于500/5时,第一个点扔油所用油5a又超过了500,所以x=500+500/3+500/5即为边界条件,此时耗油1500.
接下来每多走1公里须多耗7升油,持续到7a>500;
再接下来每多走1公里须多耗9升油,持续到9a>500;
。。以此类推
如样例中x=1000 即500+500/3+500/5+。。。+500/13+22.4331 所以耗油500*7+22.4331*15=3836.497
*注:大于500距离无法完全利用油,小于500距离不划算
(但如何证明这样的走法是最优的呢?)
趣题,所以把题面也搬过来
穿越沙漠 时间限制: 1秒 内存限制: 64M Problem Description 一辆吉普车来到 x 公里宽的沙漠边沿 A 点,吉普车的耗油量为 1 升 / 公里,总装油量为 500 升。通常,吉普车必须用自身油箱中的油在沙漠中设置若干个临时储油 点,才能穿越沙漠的。假设在沙漠边沿 A 点有充足的汽油可供使用,那么吉普车从 A 点穿过这片沙漠到达终点 B ,至少要耗多少升油。请编写一个程序,计算最少的 耗油量(精确到小数点后 3 位)。 ( 1 )假设吉普车在沙漠中行进时不发生故障; ( 2 )吉普车在沙漠边沿 A 点到终点 B 的直线距离为 x ≧ 500 公里 ( 即沙漠宽度 ) ; Input 输入的第一行含一个正整数 k ,表示测试例的个数。后面紧接着 k 行,每行对应一个测试例,包含一个正整数 x ,表示从 A 点到 B 点的距离( 1<=x<=2000 )。 Output 每个测试例对应一行输出,包含一个数,表示最少的油耗量(精确到小数点以后 3 位)。 Sample Input 2 500 1000 Sample Output 500.000 3836.497
想好久想不出来。。智商捉鸡啊。。一开始觉得是递推、DP之类的怎么搞都搞不出来。然后看了各种题解,还是没法严谨地证明,不过大概意思懂了。
比较数学化的推理参看/article/10284949.html比较形象化的解释:
x<=500 那么无须在中途扔油,耗油量就等于x,在边界x=500处,耗油500;
500<x<=500+500/3 此时为了最后一次能跑完超过500的距离,必须在终点前500距离扔油(*),如图所示。那么总共所需油为3a+500 也就是在这一阶段,每增加1公里路程,需要多用3升油(2升用来往返扔油,1升是多走1公里所用的油)。但是当a这一段多出来的距离大于500/3时,3a>500,也就是从起点去扔油的所需的油都已经超过了500,那么就需要再多扔一次油。所以边界条件为X=500+500/3时,此时耗油1000.
500+500/3<x<=500+500/3+500/5 此时需要扔两次油,位置如图。为何第一个点要扔3a呢?因为接下来第二次扔油的一个来回多走了2a,最后穿过沙漠的那一次多走了a,所以要扔3a的油。此时耗油为5a+1000,即每增加1公里路程,需要多用5升油。当a大于500/5时,第一个点扔油所用油5a又超过了500,所以x=500+500/3+500/5即为边界条件,此时耗油1500.
接下来每多走1公里须多耗7升油,持续到7a>500;
再接下来每多走1公里须多耗9升油,持续到9a>500;
。。以此类推
如样例中x=1000 即500+500/3+500/5+。。。+500/13+22.4331 所以耗油500*7+22.4331*15=3836.497
*注:大于500距离无法完全利用油,小于500距离不划算
(但如何证明这样的走法是最优的呢?)
#include<iostream> using namespace std; int main() { int t,i; double sum,x; scanf("%d",&t); while(t--) { scanf("%lf",&x); for(sum=0,i=1;x-500.0/i>=0;i+=2) { sum+=500,x-=500.0/i; } printf("%.3lf\n",sum+x*i); } return 0; }
相关文章推荐
- 2013寒假练习 1010:Maximum Sum
- BIT寒假练习-2013__1009:Number Sequence
- 2013寒假练习 1004:Who is the Smartest Man
- 2013寒假练习 1013:Bone Collector
- 2013寒假练习 1020:小白鼠
- BIT寒假练习-2013__1010:Maximum Sum
- 2013寒假练习 1017:To the Max
- 2013寒假练习 1046 Leftmost Digit
- 2013寒假练习 1057 SUM
- 2013寒假练习 1000:a+b
- BIT 1005 穿越沙漠
- 2013寒假练习 1047 Fibonacci Numbers
- 2013寒假练习 快速幂三弹连发 A^B mod C v1.0-3.0
- 2013寒假练习 1018:没有上司的聚会
- 2013寒假练习 1063 食物链(另1062 Find them, Catch them,1061 Ubiquitous Religions)
- 2013寒假练习 1011 Maximum Sum II
- 2013寒假练习 1035 远古石碑
- BIT寒假练习-2013__1012:导弹防御问题
- 2013寒假练习 1001:Average Numbers
- 2013寒假练习 1014:Big Event in BIT