穿越沙漠

来源:互联网 发布:站外优化包括什么 编辑:程序博客网 时间:2024/04/19 06:23

原题目: 穿越沙漠


要穿越沙漠,吉普车需要利用油箱的油在沙漠中设立临时储油点(即车要在两个相邻储油点间来回送油),要求出最少的总用油量能使通过沙漠.

本题考察递推算法,难点当然在于递推公式(相邻储油点间油量,距离到关系)的推导.在正面(从起点到终点)推导失败到情况下,我开始尝试从反面(从终点到起点)推导.

首先要达到该结果,有几个条件必须满足:车在相邻两个储油点间必须行驶奇数次;车每次一个(前一个定义为靠近起点)储油点出发时油箱中必须是满的;车每次到达下一个(下一个定义为靠近终点)储油点是油箱必须是空的(对于在两相邻储油点的最后一次行驶,到达下一个储油点时油箱不空,可以成将油箱剩余的油放置在储油点,出发时).


满足以上条件即可推导两个相邻储油点间关系:

设相邻储油点间距为x;

车在储油点间往返次数设为2*a + 1;

第i个储油点(储油点从终点到起点编号)储油量为oil[i],距终点距离为dis[i];

若从后向前推导,则在确定第i个储油点的情况时,oil[i - 1]与dis[i - 1]均为已知,且满足

1). oil[i - 1] = a*(500 - 2*x) + 500 - x = 500*(a + 1) - (2*a  + 1)*x;

2). oil[i] = oil[i - 1] + (2*a + 1)*x;

3). dis[i] = dis[i - 1] + x;


所以oil[i] = 500*(a + 1);

其中a = i - 1;简要证明如下:

若要最终总用油最少,一段路程,行驶次数越少越好,所以只要证明该次数不能少于(2*i - 1)次即可,可以反证:对于1储油点和0好储油点(终点),1号储油量需要500L,距终点500km(保证能到达终点,且用油最少);0号储油为0,距终点为0;则在1号和0号间需要往返1 = 2 * 1 - 1次,得证.

所以oil[i] = 500 * i;   oil[i - 1] = 500*i - (2*i - 1)*x = 500*(i - 1);

所以x = 500/(2*i - 1);


AC代码:

/*1Y    0.004s     0K*/#include <stdio.h>int main(){int T;int n;int i;double ans,s;//ans表示第i个储油点油量,s表示该点到终点距离while(scanf("%d",&T) != EOF){while(T --){ans = 0;scanf("%d",&n);if(n <= 500){//n小于500,直接可达printf("%.3lf\n",1.0*n);} else {//n大于500,需设立储油点ans = s = 0.0;i = 0;while(s < n){i ++;s += 1.0*500/(2*i - 1);//s[i] = s[i - 1] + 1.0*500/(2*i - 1)ans += 500;//ans[i] = 500i;}//处理最后的一段s -= 1.0*500/(2*i - 1);ans = ans -500 + (2*i - 1)*(n - s);printf("%.3lf\n",ans);}}}return 0;}

原创粉丝点击