1042:Gone Fishing

贪心
思路:
按贪心法的原则,要每次都选择能够得到最大收益的湖泊来钓,即钓一次鱼之后,就要再次寻找最优的湖前去钓。这样看起来的话,如何计算路上花费的时间就是一个很纠结的问题。
所以,本题思路的一个关键点在于:究竟需要在路上花费多少时间。

通过例子来说明。
假设现在有3个湖,编号为1、2、3,现提出两种钓鱼方案:
(1)1->3->2->3->1
(2)1->1->2->3->3
这两种方案,单看路上花费的时间,显然方案2更优。而这两种方案所得的鱼量呢?仔细想想,事实上没有区别。
也就是说,只要确定了最远要走到哪个湖,并按照贪心算法作出了第一种方案,那么完全可以将路线转换为方案二,鱼量不会有任何损失。
那么你在路上所花费的总时间就已经确定了,也就是一条直线走到最后所需的时间。

Ps:对本题,若所有湖都已经空了,并且时间还有剩余,默认要把剩余时间全部计入第一个湖的时间。
参考:https://blog.csdn.net/harrypoirot/article/details/25073835
AC代码:

//贪心算法
#include <iostream>
#include <cstring>
using namespace std;

int ans[30][30], f[30], d[30], t[30];

int main() {
	int h, n;//时间,湖泊数
	cin >> n;
	while (true) {
		if (n == 0) break;
		cin >> h;
		h *= 12;
		memset(ans, 0, sizeof(ans));
		memset(f, 0, sizeof(f));
		memset(t, 0, sizeof(t));
		memset(d, 0, sizeof(d));

		for (int i = 1; i <= n; i++)
			cin >> f[i];
		for (int i = 1; i <= n; i++)
			cin >> d[i];
		for (int i = 1; i < n; i++)
			cin >> t[i];
		int ht, ft[30];
		for (int ed = 1; ed <= n; ed++) {//枚举最远会走到哪个湖
			memset(ft, 0, sizeof(ft));
			for (int i = 1; i <= ed; i++)
				ft[i] = f[i];//ft作为f的临时记录
			ht = h;//记录剩余时间
			for (int i = 1; i < ed; i++)
				ht -= t[i];//减去路上的时间花费
			int k, emp = 1;//emp标记连续的已经空了的湖
			while (ht > 0 && emp <= ed) {//时间用完或湖空为止
				k = 1;
				for (int j = emp; j <= ed; j++) {//找出最优的湖
					if (ft[j] > ft[k])
						k = j;
				}
				ans[ed][0] += ft[k];//此次收获+ft[k]
				++ans[ed][k];//记录在k湖花费了1单位时间
				--ht;//时间消耗1单位
				ft[k] -= d[k];//鱼减少
				ft[k] = ft[k] > 0 ? ft[k] : 0;
				for (int j = emp; j <= ed; j++) {//检查空湖
					if (ft[j] == 0) ++emp;
					else break;
				}
			}
			if (ht > 0)//时间剩余,加到第1个湖
				ans[ed][1] += ht;
		}
		int a = 1;
		for (int i = 2; i <= n; i++) {//找出收益最大的方案
			if (ans[i][0] > ans[a][0])
				a = i;
		}
		for (int i = 1; i <= n; i++) {
			cout << ans[a][i] * 5;
			if (i != n) cout << ", ";
		}
		cout << endl;
		cout << "Number of fish expected: " << ans[a][0] << endl;
		cin >> n;
		if (n != 0)	cout << endl;
	}
	return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值