poj1042解题报告

来源:互联网 发布:班车路线查询软件 编辑:程序博客网 时间:2024/05/20 12:25

Gone Fishing Time Limit: 2000MS Memory Limit: 32768K Total Submissions: 17253 Accepted: 4810 Description John is going on a fishing trip. He has h hours available (1 <= h <= 16), and there are n lakes in the area (2 <= n <= 25) all reachable along a single, one-way road. John starts at lake 1, but he can finish at any lake he wants. He can only travel from one lake to the next one, but he does not have to stop at any lake unless he wishes to. For each i = 1,...,n - 1, the number of 5-minute intervals it takes to travel from lake i to lake i + 1 is denoted ti (0 < ti <=192). For example, t3 = 4 means that it takes 20 minutes to travel from lake 3 to lake 4. To help plan his fishing trip, John has gathered some information about the lakes. For each lake i, the number of fish expected to be caught in the initial 5 minutes, denoted fi( fi >= 0 ), is known. Each 5 minutes of fishing decreases the number of fish expected to be caught in the next 5-minute interval by a constant rate of di (di >= 0). If the number of fish expected to be caught in an interval is less than or equal to di , there will be no more fish left in the lake in the next interval. To simplify the planning, John assumes that no one else will be fishing at the lakes to affect the number of fish he expects to catch. Write a program to help John plan his fishing trip to maximize the number of fish expected to be caught. The number of minutes spent at each lake must be a multiple of 5. Input You will be given a number of cases in the input. Each case starts with a line containing n. This is followed by a line containing h. Next, there is a line of n integers specifying fi (1 <= i <=n), then a line of n integers di (1 <=i <=n), and finally, a line of n - 1 integers ti (1 <=i <=n - 1). Input is terminated by a case in which n = 0. Output For each test case, print the number of minutes spent at each lake, separated by commas, for the plan achieving the maximum number of fish expected to be caught (you should print the entire plan on one line even if it exceeds 80 characters). This is followed by a line containing the number of fish expected. If multiple plans exist, choose the one that spends as long as possible at lake 1, even if no fish are expected to be caught in some intervals. If there is still a tie, choose the one that spends as long as possible at lake 2, and so on. Insert a blank line between cases. Sample Input 2 1 10 1 2 5 2 4 4 10 15 20 17 0 3 4 3 1 2 3 4 4 10 15 50 30 0 3 4 3 1 2 3 0 Sample Output 45, 5 Number of fish expected: 31 240, 0, 0, 0 Number of fish expected: 480 115, 10, 50, 35 Number of fish expected: 724 题目大意: 我English反面严重吃紧,在有道词典的帮助下翻译出大意如下。 John正在进行钓鱼,他有h个小时可以钓(1<=h<=16),这里有n个湖(2<=n<=25),都只能单向通过一次。John从湖1开始,并能在时间允许下完成他想钓鱼的湖,他只能从一个湖到接着的下一个湖,不一定停下。他从第i个湖到第i+1个湖路上所需时间记为t[i]。为了完成这次钓鱼旅行,他了解了每个湖最初5分钟所能钓到鱼数量的期望值,用数组f[ ]记录。还有每个湖开始钓鱼后以5分钟为周期所能钓到鱼数量期望值减少数量用d[ ]储存。例如在第i个湖头五分钟能钓f[i]条,第2个五分钟能钓f[i]-d[i]条,之后每五分钟减d[i]条...... 现在我们要给出一个让John在给定条件下钓最多鱼的解决方案,假设只有John自己在钓鱼,输入第一行n为湖的数量,第二行h为他有的时间,单位是小时,第三行是f[],第四行是d[],第四行是t[]。循环输入多组数据,当n输入为0时程序结束。输出为每个湖停留的分钟数,用逗号加空格隔开。在输出可以掉到的最多鱼是多少。千万要注意输出一组数据后要空一行。 解题思路: 用贪心算法,很多人做这道题用较难的dp算法来做,因为确实很难想到能用贪心来做。我也是在学校的讲义中对这题说明才知道。 题目中可以钓到鱼的数量是以5分钟为单位变动的,于是不难想出贪心的标准就是选每个5分钟选可以钓到鱼最多的鱼的湖。但是我们还要考虑在路上耗费的时间,到的湖越远,路上用时越多,能用于钓的时间就越少,所以不能直接进行这样比哪个湖鱼多的贪心。于是想到,如果确定John最远到了哪个湖,就确定了路上的耗时,用总时间减去路上耗时,剩下的时间就直接按每个五分钟比较哪个湖鱼多分配,哪个湖鱼多就在哪个湖停留,我用数组sp[i]记录在第i个湖停留时间,每在i湖停一次,sp[i]=sp[i]+5,i湖的鱼减少d[i]。 现在问题就剩下怎么知道John最远到了哪个湖?我瞎想了几种方法想蒙一下都没得逞,自己也都发现错在哪。不能解决,百度出有高手介绍这题用枚举加贪心做才恍然大悟,我们的讲义中说用贪心没说用到枚举,我就没想到,明显我还比较菜,不具备对这些有水平题目分析确定解题策略的能力,需要指点才行啊。以后要继续努力提高。我们现在是不知道John最远到哪个湖才能钓的最多,就假设他最远到湖1,湖2....湖n。也就是把所有湖作为最远枚举一遍。比较以哪个湖最远钓的鱼最多就确定这个方案了。 下面给出源代码,先读入参数n,判断0结束,不是0则传入run(n)函数求解这组数据。distribution_time函数完成对每个湖停留时间的分配,因为所给时间可能不够把每个湖都去到,所以我写了一个farthest函数确定最远跑哪个湖时间光在路上就用完,后面就不需要枚举了,这样可优化算法,但因原来效率以符合要求没用还没使用。 #include int run(int n) { int t[100],f[100],d[100],sp[100],sp2[100],ff[100]; int h,m,stay; int i,j,max,ft,x,g; g=0; scanf("%d",&h); for(i=1;i<=n;i++) { scanf("%d",&f[i]); if(f[i]>0) g=1; } for(i=1;i<=n;i++) scanf("%d",&d[i]); for(i=1;i0) { l=1; for(i=2;i<=ft;i++) { if(f[i]>f[l]) l=i; } sp2[l]=sp2[l]+5; if(f[l]>0) { max=max+f[l]; f[l]=f[l]-d[l]; if(f[l]<0) f[l]=0; } m=m-5; } return max; } int main() { int n; while(1) { scanf("%d",&n); if(n==0) break; else run(n); } return 0; } 还需要注意的是考虑f[ ]全为零的情况,还有i湖中可掉到的鱼每次减d[i]后可能得到负数,如果是负数的话要设为0,这相当重要,我就是这一点错后浪费了大量的青春。还有事按题目要求,多出来的时间都要给第一个湖。这题可能出现的错误很隐蔽,所以弄得大家很纠结,从poj的discuss里面的留言之多,讨论之热烈可看出,做出后相当有成就感