解析:由于路径的输出要求,这里使用逆推的方式更加合适。
设dp[i][j]为从i开始,剩余时间为j的最大捕鱼量。
枚举在第i个湖上钓鱼的时间k,则有dp[i][j] = max(dp[i+1][j-k]+k时间内能钓到的鱼的数量)
[code]:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,f[30],d[30],t[30],dp[30][200],pr[30][200];
int tim[30],top;
void init(){
memset(dp,-1,sizeof(dp));
memset(pr,-1,sizeof(pr));
int num,j;
for(j=0;j<=m;j++){
num = d[n-1]?min(j,(f[n-1]-1)/d[n-1]+1):j;
dp[n-1][j] = num*(2*f[n-1]-(num-1)*d[n-1])/2;
}
}
int main(){
int i,j,k,cas;
scanf("%d",&cas);
for(int T=1;T<=cas;T++){
scanf("%d%d",&n,&m);
m *= 12;
for(i = 0;i < n;i++) scanf("%d",&f[i]);
for(i = 0;i < n;i++) scanf("%d",&d[i]);
for(i = 0;i < n-1;i++) scanf("%d",&t[i]);
init();
int num,tmp;
for(i = n-2;i >= 0;i--){
for(j = 0;j <= m;j++){
num = d[i]?min(j,(f[i]-1)/d[i]+1):j;
dp[i][j] = num*(2*f[i]-(num-1)*d[i])/2;
for(k = j;k >= t[i];k--){
num = d[i]?min(k-t[i],(f[i]-1)/d[i]+1):(k-t[i]);
tmp = dp[i+1][j-k]+num*(2*f[i]-(num-1)*d[i])/2;
if(dp[i][j] < tmp){
dp[i][j] = tmp;
pr[i][j] = j-k;
}
}
}
}
printf("Case %d:\n",T);
int t1,t2;
t1 = 0,t2 = m;top = 0;
while(t2 != -1){
tim[top++] = t2 - (pr[t1][t2]==-1?0:(pr[t1][t2]+t[t1]));
t2 = pr[t1][t2];
t1++;
}
for(;t1 < n;t1++) tim[top++] = 0;
for(i = 0;i < top;i++){
if(i) printf(", ");
printf("%d",tim[i]*5);
}
printf("\nNumber of fish expected: %d\n",dp[0][m]);
}
return 0;
}