“请你编程”95001讲评 广州 陆文杰 1995-03-31 汽车穿越沙漠的整个过程是怎样的呢?广西覃东晟同学画出了下面的示意图: 这个图说明:不管加油站定在何处,均可如图对它们编号,而且1、2站之间的路程必定经过了三次(因为经过次数愈多耗油也越多),2、3号站之间必定经过了五次。归纳之,i号加油站和i+1号加油站之间必定经过了2i+1次。 由于要求汽车所走的路程最短,那么各站之间的距离应尽量远。由题意,1号加油站应设在距终点500公里处。假设第2号加油站应在距第1号x公里处,这时必有3x+500≤2*500,也即x≤500/3(其中3x是2号到1号之间的耗油量)。因各站之间距离应尽量远,故取x=500/3,类似的分析可得第3号加油站应设在距离第2号500/5公里处。运用归纳法,第i+1号加油站应设在离i号500/(2i+1)公里处。 有了上面的分析,编程求最小耗油是不难的。湖北吴云洋用C语言编程如下: #include #define M 1000#define N 500Void main(){float s=N;/*S:这个加油站离终点的距离*/float p=M;/*P:终点或中途加油站离始点的距离*/ int i=1;/*倒数第i个加油站*/ do printf("倒数第%d个加油站在离起点%.3f公里处。\n",\i,p-=(float)N/(2*i-1); while((s+=(float)N/(++i*2-1))500 THEN P=(500-X)*YX=X+P/YZ=Z+PPRINT "距终点";500-X;"公里,";"拥有油量";ZWENDEND 湖南李南松避开了耗时较大的浮点运算,他的程序执行速度极快: #define MaxLoad 50000000L#define MaxLen 100000000Lint main(){long len,total=0;je=0;/*total:累计用油,je:累计距离*/long count;/*各站间路段最少驾车次数*/int k=0;/*路段计数*/while(1){if((total-1)%(MaxLoad-2)==0)count=(total-1)/(MaxLoad-2);else count=(total-1)/(MaxLoad-2)+1;len=(MaxLoad*conut-total)/(2*count-1);if(je+=len)≥MaxLen)}len=MaxLen=je+len;printf("k=%d len=%f oil=%f\n",k,(float)len/1.0E5,(float)total/1.0E5);total+=len*(2*count-1);break;}printf("k=%d len=%f oil=%f\n",k,(float)len/1.0E5,(float)total/1.0E5);total+=len*(2*count-1);k++;}printf("Total=%f\n",total/1.0E5);} 上面程序是基于这样一个事实,即500*count-(2*count-1)*len(>=+total也即count>=(total-len)/(500-2*len),要count的最小值,必有len=1,故count为不小于(total)/(500-2)的最小整数。 也有少数读者采用直接搜索法,这样的解法似乎更令人信服。如广西陆秀忠的程序也相当漂亮,但限下篇幅,这次的讲评就到此为止了。 最后我们采用电脑抽奖法确定了10名作为这次“请你编程”的幸运者,他们是: 广西 陆秀忠 四川 曹林 浙江 李南松 湖北 吴云洋 浙江 胡茂华 安徽 刘险峰 四川 花仕良 安徽 丁美怀 上海 林孙义 广州 陆文杰 [本期题目]95003 请编一个电脑抽奖程序,在输入候奖人数、人名及获奖人数后,电脑按照机会均等原则确定出获奖者名单。要求:程序简洁,结构清晰、操作方便、算法合情合理。