问题描述
John有h个小时的时间想去钓鱼。(1<=h<=16).有n个池塘(2<=n<=25),它们的分布沿着一条单行的小路。John从第一个池塘处出发,他可以沿着小路向前走,在想停下来的池塘处钓鱼,对于路径的终点没有限制。为了钓到最多的鱼,John对各个池塘做了调查。若给路径上的池塘依次编号,,则对于每个池塘,开始钓鱼时,每5分钟内期望是可以钓到f[i]条鱼,随着时间的推移,每过5分钟,可以钓到的鱼减少d[i]条。若某个5分钟的时间段内可以钓到的鱼少于等于d[i],则下一个5分钟在这个池塘就钓不到鱼了。用t[i]表示从池塘 i 到池塘 i+1 所需要的时间。单位是5分钟, 即:若t[3] = 4,表示从池塘3到池塘4需要4*5=20分钟。John在每个池塘钓鱼的时间都必须是5的倍数。求期望能钓到最多鱼的钓鱼计划,并输出在每个池塘钓鱼的时间(分钟为单位)和能钓到的鱼总数。当有多个方案都是最优解时,选择在第一个湖的时间最长的方案,若仍相等,选择在第二个湖时间最长的方案,依此类推。
输入
每个测试用例,首先给出池塘数n,然后是时间h(小时为单位),接下来的两行分别有n个整数,分别表示f[i]和d[i],接下来的一行为n-1个整数,表示t[i].n为0时表示输入结束。
例如:
2
1
10 1
2 5
2
4
4
10 15 20 17
0 3 4 3
1 2 3
输出
对于每个测试用例,第一行依次输出在每个池塘的停留时间(分钟为单位),每个时间之间用逗号+空格分开。第二行输出能钓到的最多的鱼的数量,格式见Sample.
解题思路
我们可以把总时间分为两个部分:在路上的时间和在钓鱼的时间。由于路是单行的,所以在路上的时间取决于走的最远距离,即到达的池塘的最大编号。 剩余的时间用于钓鱼。我们可以把移动+钓鱼的混合过程拆分为移动的过程和钓鱼的过程,即指定一个池塘为终点,移动过程即从起点到终点的过程,钓鱼的过程就是从起点到终点的各个池塘中选择池塘钓鱼,因为移动过程所需的时间已经在前面考虑过了,这个时候我们就可以认为需要移动的时候可以直接瞬间到达。然后,选择到哪些池塘钓鱼的策略采用贪心的方法,每个钓鱼的5分钟都选择期望最大的那一个池塘,每在选择一个池塘钓鱼5分钟,减少相应池塘的期望,增加计划中在该池塘钓鱼的时间,然后继续选择期望最大的池塘,直到钓鱼的时间不够,或者池塘里没有鱼了。如果池塘没有鱼了,还有时间的话,把多余的时间分配给第一个池塘
具体代码
#include <iostream>
#include <cstring>
#include <climits>
#define N 25
using namespace std;
int main(void)
{
int n, h;
int fi[N], di[N], ti[N];//fi[]期望钓鱼数, di[]每五分钟减少鱼数, ti[]位移时间
int time[N];//在当前湖停下来时在每个湖停留的时间
int best[N];//最优解对应的在每个湖停留的时间
int bestFishNum;//最优解钓鱼总数
int fishNum;//当前钓鱼总数
while (cin >> n && n)
{
cin >> h;
h *= 12;//共有h个5分钟
for (int i = 0; i < n; i++) cin >> fi[i];//期望钓鱼数
for (int i = 0; i < n; i++) cin >> di[i];//每五分钟减少鱼数
for (int i = 0; i < n - 1; i++) cin >> ti[i];//位移时间
bestFishNum = INT_MIN;
memset(best , 0 , sizeof best);//将best数组的值全部设为0
for (int p = 0; p < n; p++) {//穷举最终停下的湖的位置
memset(time , 0 , sizeof(time));
fishNum = 0;
int remainingTime = h;//当前剩余时间
int remainingFish[N];//当前在每个湖剩余能钓的鱼的数目
for (int i = 0; i < n; i++)
remainingFish[i] = fi[i];//初始化
for (int j = 0; j < p; j++)
remainingTime -= ti[j];//先减去路程,之后假设John可以在lake 0到lake i之间随意位移
while (remainingTime > 0) {//直到时间用尽
int max = INT_MIN;
int pos = 0;//当前能钓鱼最多的位置
for (int j = 0; j <= p; j++)//每次选出能钓鱼最多的位置
if (remainingFish[j] > max)
{
max = remainingFish[j];
pos = j;//找到位置
}
time[pos]++;//对应时间++
fishNum += remainingFish[pos];//累加钓鱼数
remainingFish[pos] =remainingFish[pos]- di[pos]>0?remainingFish[pos]-di[pos]:0;
remainingTime--;
}
if (fishNum > bestFishNum)
{
bestFishNum = fishNum;
for (int i = 0; i < n; i++)
{
best[i] = time[i];
}
}
}
for (int i = 0; i < n - 1; i++)
cout << best[i] * 5 << ", ";
cout << best[n - 1] * 5 << endl;//注意输出格式
cout << "Number of fish expected: " << bestFishNum << endl << endl;
}
return 0;
}