NYOJ 30 Gone Fishing JAVA+解析

Gone Fishing这道题目运用的多次折合成一次这种思想我首次见,我想的一个思路是,每次算一下鱼量和时间代价比,这个代码我没有敲,下面的代码是一位仁兄敲得,我研读了一下,做了一个注释,应该有利于后来者进行研读。

 

这次代码中都加了注释,应该满足博客园的规定了~~

Gone Fishing

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 5
 
描述
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. 
 
输入
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. 
输出
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. 
样例输入
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 

样例输出
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 
  1 //NYOJ 30 Gone Fishing

  2 

  3 

  4 import java.util.*;

  5 public class Main{

  6     public static void main(String args[]){

  7         Scanner keyin=new Scanner(System.in);

  8         

  9 // 对所有的下标,均从1开始,所以所有的数组都多开了一个值

 10         

 11 /*该算法建立在一个假设的基础上,即捕鱼者可以在池塘间可以瞬移,即其一次计

 12  * 算完其在从1到i个池塘的时间,多次折返在池塘间,认为并未折返,将其多次

 13  * 折返视为1次在1个池塘采集够所需的鱼量。

 14  *  

 15  */

 16 

 17         //输入湖的数量

 18         int n=keyin.nextInt();

 19         

 20         

 21         lable:

 22         while(n!=0){

 23             if(n<2||n>25) break;   //对值的过滤

 24             int i=0;

 25             int x=0;

 26             int tt[][]=new int[n+1][n+1]; //多开一个数组位置,从1开始  记录尝试的所有捕鱼序列

 27             int j=0;

 28             int m=0;

 29 

 30             int max2=-1;

 31             int index2=0;

 32 

 33 

 34 

 35             int f[]=new int[n+1]; //池塘的初始第一次捕鱼量

 36             int d[]=new int[n+1]; //池塘除第一次捕鱼后每次递减常量

 37             int t[]=new int[n+1]; //池塘之间跨越所消耗的时间  从第i个池塘到i+1个池塘

 38             Arrays.fill(t,0);

 39 

 40         //输入时间 

 41         int h=keyin.nextInt();   //捕鱼的总时间

 42         if(h<1||h>16) break;     //对值的过滤

 43         

 44         

 45         //输入每个湖第一次钓鱼数

 46         for(i=1;i<=n;i++){

 47             f[i]=keyin.nextInt();

 48             if(f[i]<0) break lable;

 49         }

 50         

 51         

 52         //输入第一次之后每五分钟减少的鱼量

 53         for(i=1;i<=n;i++){

 54             d[i]=keyin.nextInt();

 55             if(d[i]<0) break lable;

 56         }

 57         

 58         

 59         //输入从第i到i+1个湖所用时间t[i]

 60         for(i=1;i<=n-1;i++){

 61             t[i]=keyin.nextInt();

 62             if(t[i]<=0||t[i]>162)

 63                 break lable;

 64         }

 65         

 66         

 67         //每次选择鱼量最多的湖            

 68         for(x=1;x<=n;x++){                //从第一个湖开始遍历,寻找所有可能的捕鱼序列(这样也满足尽量从1、2号等池塘捕捞的原则)

 69             int time=0;

 70             int sum[]=new int[n+1];        

 71             int index;

 72             int max=-1;

 73             Arrays.fill(sum,0);

 74             for(i=1;i<x;i++) time+=t[i];  //计算从第1个池塘到达第x个池塘所话费的时间time

 75             m=(60*h-5*time)/5;       //计算到达池塘后还有多少时间,够捕鱼的次数m

 76             

 77             

 78             int fishtime[]=new int[x+1];

 79             

 80             

 81             for(int a=1;a<=x;a++)                  //拷贝池塘的初始捕鱼量,防止因为修改值而使后面的代码无值可用

 82                 fishtime[a]=f[a];//copy fi         //每次拷贝从1到x的池塘的数据

 83             

 84             while(m>0){   //如果还有时间捕鱼

 85                 m--;    //减少可捕鱼次数

 86                 max=fishtime[1];     //设置初始最大捕鱼量为fishtime【1】

 87                 index=1;               //初始记录数组的横坐标为1

 88                 

 89                 for(j=1;j<=x;j++){         //如果在1到x的池塘中,捕鱼量超过max的,则交换max,记录当前j到index中,找到最大可捕鱼量

 90                     if(fishtime[j]>max){

 91                         max=fishtime[j];

 92                         index=j;

 93                     }

 94                 }

 95                 

 96                 fishtime[index]-=d[index];  //当前的fishtime【index】最大捕鱼量按照其递减常量减少

 97                 tt[x][index]++;      //tt当前横坐标的最大值++

 98                 sum[x]+=max;        //当前捕鱼量增加max

 99                   if(fishtime[index]<=0)          //如果当前池塘的可捕鱼小于0,则下一次将没有鱼可以捕捞

100                       fishtime[index]=0;

101             }

102             

103             

104             if(sum[x]>max2){    //如果当前的捕鱼总量大于记录的全局最大值 则重新记录

105                 max2=sum[x];

106                 index2=x;    //寻找最大的捕鱼序列的  横坐标值(其为二维数组)      【横坐标为其是第几次记录的最大的池塘依次捕鱼序列】

107             }

108         }

109         for(int k=1;k<n;k++)

110             System.out.print(5*tt[index2][k]+", ");

111         System.out.println(5*tt[index2][n]);

112         System.out.println("Number of fish expected: "+max2);

113         n=keyin.nextInt();

114         if(n!=0)

115             System.out.println();

116     }

117 }

118 }

你可能感兴趣的:(java)