【BIT乐学】Gone fishing【贪心+枚举】

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 

题目大意

这题大意就是说John去钓鱼,单方向逐个经过n个湖,可以在任意湖停止,第i个湖一开始都有fi条鱼,每钓鱼5min就会减少di条鱼,也就是说第一个5min可以钓鱼fi条,第二个5min只能钓鱼fi-di条,如果fi比di小,则本次5min钓鱼结束后这个湖里就没有鱼可以钓了。然后第i湖到i+1湖之间需要耗时ti(单位5min),然后给出总时间h小时,最多的钓鱼数量。如果有相同的解,那么选择靠前的湖时间更长的方案。


个人思路

这题的思路是贪心+枚举,总共有n个湖,那么就枚举停在n个湖下各自的最优方案,然后选择这n个方案中最好的。停留在某个湖下的方案通过贪心进行计算,因为确定了停止的湖,也就确定了路程所消耗的时间,则可以计算出用来钓鱼的总时间。每次钓鱼都从当前选择方案的这几个湖中选择鱼量最大的湖,选择结束后将该湖的停留时间增加5min,该湖的鱼量减少di,总钓鱼事件减5min。通过循环将所有的钓鱼事件用完或者所有的鱼调完,则该方案的贪心最优解求得。

有以下几个注意点:

  1. 每次选择鱼量最大的湖可以使用结构体的优先队列,重载操作符<的时候优先级是鱼量从大到小,鱼量相同的情况下id较小的优先。
  2. 更新时如果fi比di小,那也是将这么多fi钓完之后才没有鱼的,之前就是因为这点没注意到WA了好几发。
  3. 注意输出格式,冒号和逗号后面都还有空格,每两个样例之间需要有一行空行,因为格式也WA了几发。

实现代码

#include <cstdio>
#include <iostream>
#include <queue>
#include <string.h>

using namespace std;

const int MAXN = 25;

struct Lake
{
	int fi, di, index;
	
	friend bool operator < (const Lake &a, const Lake &b) {
		if (a.fi != b.fi) return a.fi < b.fi;
		else return a.index > b.index;
    }
}; 

int main()
{
//	freopen("1.txt", "r", stdin);
	int n, h;
	int ti[MAXN];  // ti:时间间隔 
	Lake lakes[MAXN];
	int spent_time[MAXN];
	bool output_flag = false;
	
	while (cin >> n && n) {
		// Init
		memset(spent_time, 0, sizeof(spent_time));
		memset(lakes, 0, sizeof(lakes));
		memset(ti, 0, sizeof(ti));
		
		// Input
		cin >> h;
		for (int i = 0; i < n; i ++) {
			cin >> lakes[i].fi;
		}
		for (int i = 0; i < n; i ++) {
			cin >> lakes[i].di;
			lakes[i].index = i;
		}
		for (int i = 0; i < n-1; i ++) {
			cin >> ti[i];
		}
		
		// 将小时转换成5min
		h *= 12; 
		
		//最终最优结果 
		int ans = 0;  
		
		// 枚举停留在每个湖的情况,每种情况内部用贪心解决
		for (int i = 0; i < n; i ++) {
			int fish_num = 0;  // 本次贪心钓鱼数量 
			
			int lake_time[n];  // 本次贪心在每个湖上的钓鱼时间 
			memset(lake_time, 0, sizeof(lake_time));
			
			// 剩下的钓鱼时间
			int t_fishing = h;
			
			// 存储每次钓鱼最大值的优先级队列
			priority_queue<Lake> q;
			for (int j = 0; j <= i; j ++) q.push(lakes[j]);
			
			// 当钓鱼时间还有剩余 
			while (t_fishing > 0) {	
				if (q.top().fi > 0) {  // 当栈顶最大鱼量>0时,钓鱼,更新栈顶数据 
					fish_num += q.top().fi;
					Lake temp = q.top();
					q.pop();
					if (temp.fi < temp.di) temp.fi = 0;  // 如果本次的鱼量小于减小值,则将下次该湖鱼量设为0 
					else temp.fi -= temp.di;
					q.push(temp);
					lake_time[temp.index] += 1;
				}
				else {  // 如果最大鱼量为0,则将剩余时间都放在第一个湖上 
					lake_time[0] += t_fishing;
					break;
				}
				t_fishing --;  // 每次钓鱼更新时间 
			}
			
			// 更新钓鱼总时间,没枚举到下一个目的湖,就把剩余时间减去路程时间 
			if (i < n-1) h -= ti[i]; 
			
			// 更新最优值 
			if (fish_num > ans) {
				ans = fish_num;
				for (int j = 0; j < n; j ++) spent_time[j] = lake_time[j];
				
			}
		} 
		
		// Output
		if (output_flag) cout << endl;
		else output_flag = true;
		
		for (int i = 0; i < n; i ++) {
			cout << spent_time[i] * 5;
			if (i < n - 1) cout << ", ";
			else cout << endl; 
		}
		
		cout << "Number of fish expected: " << ans << endl;
	}
	
	return 0;
}

总结

学习不息,继续加油

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值