描述
http://bailian.openjudge.cn/practice/1042/
约翰要去钓鱼。他有h个小时的可用时间(1<=h<=16),该区域有n个湖泊(2<=n<=25),所有湖泊都可以沿着一条单行道到达。约翰从1号湖出发,但他可以在任何他想去的湖结束比赛。他只能从一个湖到下一个湖,但除非他愿意,否则他不必在任何一个湖停留。对于每个i=1,。。。,n-1,从i湖到i+1湖的5分钟间隔数表示为ti(0<ti<=192)。例如,t3=4意味着从3号湖到4号湖需要20分钟。为了帮助计划他的钓鱼旅行,约翰收集了一些关于湖泊的信息。对于每个i湖,预计在最初5分钟内捕获的鱼的数量是已知的,表示为fi(fi>=0)。每5分钟的捕鱼会以恒定的di(di>=0)速率减少下一个5分钟间隔内预计捕获的鱼的数量。如果预计在一个时间间隔内捕获的鱼的数量小于或等于di,那么在下一个时间间隔内,湖中就不会有更多的鱼了。为了简化计划,John假设没有其他人会在湖边捕鱼,从而影响他预计捕获的鱼的数量。
编写一个程序来帮助John计划他的钓鱼旅行,以最大限度地增加预期捕获的鱼的数量。在每个湖上花费的分钟数必须是5的倍数。
输入
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
您将在输入中看到许多案例。每种情况都以包含n的行开始。这之后是包含h的行。接下来,有一行n个整数指定fi(1<=i<=n),然后是一行n个整数di(1<=i<=n),最后是一行n-1个整数ti(1<=i<=n-1)。输入被n=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
对于每个测试用例,打印在每个湖上花费的分钟数,用逗号分隔,以实现预期捕获的最大鱼数(即使超过80个字符,也应在一行上打印整个计划)。后面是一行,其中包含预期的鱼数。
如果存在多个计划,则选择在1号湖花费尽可能长时间的计划,即使预计在某些时间间隔内不会捕获任何鱼。如果仍然有平局,选择一个尽可能长时间待在第二湖的,以此类推。在案例之间插入一个空行。
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
//一般来说,如果只有一种比较排序的需求,两种方法都可以,但如果有多种排序需求,建议使用Comparator
class Lake implements Comparable<Lake>{
int f,d,id;
@Override
public int compareTo(Lake o) {
// TODO Auto-generated method stub
if(this.f==o.f) return (this.id-o.id);//this.*** - o.*** 升序
return (o.f-this.f); // o.*** -this.*** 降序
}
}
public class Main{
public static final int MAXN=25+5;
public static Lake a[]=new Lake[MAXN];
public static int n,t,ans;
public static int dis[]=new int[MAXN], best[]=new int[MAXN],tmp[]=new int[MAXN];
public static PriorityQueue<Lake> q=new PriorityQueue<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int now;
Lake node = new Lake();
//trim是为了防止末尾的空格
n =Integer.parseInt(sc.nextLine().trim());
while(n!=0) {
//读入数据
t=Integer.valueOf(sc.nextLine().trim());
t*=12;
String str = sc.nextLine().trim();
String[] split = str.split(" ");
for(int i=0;i<n;i++) {
a[i]=new Lake();
a[i].f=Integer.parseInt(split[i]);
}
str = sc.nextLine().trim();
split = str.split(" ");
for(int i=0;i<n;i++) {
a[i].d = Integer.parseInt(split[i]);
a[i].id=i;
best[i]=0;
}
dis[0]=0;
str = sc.nextLine().trim();
if(n>2) {
split = str.split(" ");
for(int i=1;i<n;i++) {
//计算从起点到终点的每个路程时间
dis[i]=Integer.parseInt(split[i-1]);
dis[i]+=dis[i-1];
}
}else {
dis[1]=Integer.parseInt(str);
}
ans=-1;
//枚举每个节点
for(int i=0;i<n;i++) {
now =0;
if(!q.isEmpty()) q.clear();
//用tmp保存临时变量,保护其他数据
for(int j=0;j<=i;j++) {
Lake tmp=new Lake();
tmp.f=a[j].f;
tmp.d = a[j].d;
tmp.id = a[j].id;
q.add(tmp);
}
for(int j=0;j<n;j++) {
//初始钓鱼数都为0
tmp[j]=0;
}
//计算可以钓鱼的时间
int tt = t-dis[i];
while(tt>0) {
node = q.peek();
q.poll();
tt--;
now+=node.f;
tmp[node.id]++;
node.f-=node.d;
if(node.f<0) node.f=0;
q.add(node);
}
if(now>ans) {
ans = now;
for(int j=0;j<n;j++) {
best[j]=tmp[j];
}
}
}
for(int i=0;i<n-1;i++) {
System.out.print((best[i]*5)+", ");
}
System.out.println(best[n-1]*5);
System.out.println("Number of fish expected: "+ans);
n=Integer.parseInt(sc.nextLine().trim());
if(n>0) System.out.println();
}
}
}