起先可以想到的贪心就是每次取所有湖中每个机会可以钓到的最多的鱼
网上说刘佳汝黑书《算法艺术与信息学竞赛》中有对这题有分析,但是黑书上没有代码,我在网上找到了对黑书中的部分题目的样例和代码,幸好里面有这题
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n, h;
while (cin >> n)
{
if (n == 0) break;
int d[26] = { 0 }, t[26] = { 0 }, f[26] = { 0 }, fs[26];
cin >> h;
h *= 12;//每一单位相当于一次机会
int i, j;
for (i = 0; i < n; i++)
cin >> f[i];
for (i = 0; i < n; i++)
cin >> d[i];
for (i = 1; i < n; i++)
cin >> t[i];
int time, k;
int ans[26][26] = { 0 };
memset(ans, 0, sizeof(ans));
//贪心 核心代码块 详细分析
//看这个二维数组,其实跟动态规划有点像?
for (i = 1; i <= n; i++)//在前 i 个湖中每次寻找鱼最多的湖下钓
{
memcpy(fs, f, sizeof(f));//把fs重新更新回原始的f
int flag = 0;
h = h - t[i - 1];//前i个湖消耗在路上的时间,剩下就全是给钓鱼的时间,
//由于是从1开始的,所以之前累积的都已经减了,每次只需减去到新增的这个湖的时间
time = h;
while (time > 0 && flag != i)//每次寻找鱼最多的湖下钓直到时间用完(机会次数time=0)或所有湖中鱼钓完(没鱼了的湖的个数flag=i)
{
k = 0;
for (j = 1; j < i; j++)
if (fs[j] > fs[k]) k = j;//找到当前所有湖中(前i个湖)剩下鱼最多的湖
ans[i][0] += fs[k];//ans[i][0]是总结果
ans[i][k + 1]++;//每个这时候湖从1到i编号(不是从0开始),表示前i个湖的每个湖使用的钓鱼的次数(到时候乘以5就是时间)
time--;
if (fs[k] > 0)
{
fs[k] -= d[k];
if (fs[k] < 0) fs[k] = 0;
}
flag = 0;
for (j = 0; j < i; j++)
if (fs[j] <= 0) flag++;
}
//将剩余时间加到一个湖中用时
ans[i][1] += time;
}
k = 1;
for (j = 2; j <= n; j++)
if (ans[j][0] > ans[k][0]) k = j;
for (j = 1; j <= n; j++)
{
cout << ans[k][j] * 5;
if (j != n) cout << ", ";
}
cout << endl;
cout << "Number of fish expected: " << ans[k][0] << endl;
cout << endl;
}
return 0;
}
感谢黑书的解析哦!