贪心+暴力,从近至远依次枚举可以到达的钓鱼地点,用总时间减去中途消耗的时间,这样就可以将其当成在各个钓鱼地点之间随意转移(实际题目中给出是单方向前行的),然后在已到达的最远的钓鱼地点之内的所有钓鱼地点上按每次钓最大值的鱼做贪心,若时间用不完,则剩余时间加到第一个钓鱼地点上。注意,钓鱼地点最初的钓鱼值可能为零。
代码如下:
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
struct fish
{
int fi, di;
} ff[27];
int main()
{
#ifdef test
freopen("in.txt", "r", stdin);
#endif
int n, h, flag = 0;
int ti[27], fk[27], save[27];
while(scanf("%d", &n) , n)
{
if(flag)
puts("");
else
flag = 1;
scanf("%d", &h);
for(int i = 0; i < n; i++)
scanf("%d", &ff[i].fi);
for(int i = 0; i < n; i++)
scanf("%d", &ff[i].di);
ti[0] = 0;
for(int i = 1; i < n; i++)
{
scanf("%d", &ti[i]);
ti[i] += ti[i - 1];
}
int max = 0, tt, sum_t = 0;
memset(save, 0, sizeof(save));
for(int i = 0; i < n; i++)
{
int sum = 0;
tt = h * 12 - ti[i];
if(tt <= 0)
break;
memset(fk, 0, sizeof(fk[i]) * (i + 1));
while(1)
{
int fflag = 0, max_fish = 0, max_j = 0;
for(int j = 0; j <= i; j++)
{
int ans = ff[j].fi - fk[j] * ff[j].di;
if(ans > max_fish)
{
max_fish = ans;
max_j = j;
fflag = 1;
}
}
if(!fflag) // 若所有地点全部钓完,则跳出
break;
sum += max_fish;
++fk[max_j];
--tt;
if(tt <= 0)
break;
}
if(sum > max)
{
max = sum;
sum_t = tt;
for(int j = 0; j <= i; j++)
save[j] = fk[j];
}
}
save[0] *= 5;
if(sum_t > 0)
save[0] += sum_t * 5;
if(!max) // 若最大值为0,即:第一个钓鱼地点初始值为0,同时时间上无法到达第二个钓鱼地点,则需特殊处理
save[0] = h * 60;
printf("%d", save[0]);
for(int i = 1; i < n; i++)
printf(", %d", 5 * save[i]);
printf("\nNumber of fish expected: %d\n", max);
}
return 0;
}