NOI 1042:Gone Fishing

描述
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();
        }
    }   
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值