您的位置:首页 > 编程语言 > Go语言

ZJU1161 Gone Fishing - 动态规划

2008-07-26 23:23 274 查看
题目描述:

一个人去n个湖钓鱼,第i个湖里初始时一个单位时间可以钓fi条鱼,下一个单位时间钓的鱼数量递减di。湖的排列是线性的,从第i个湖走到第i+1个湖需要ti的时间。现在有m时间可用,初始在第一个湖,问最多可以钓多少鱼。

分析:

很明显题目条件满足无后效性,可以用动态规划来解决。

设dp[i][j]表示在前i个湖花费j的时间最多钓鱼数量(并停留在第i个湖)。getFish(i,t)表示在第i个湖花费t时间总共获得的鱼数量。

状态转移方程:dp[i][j] = max{ dp[i-1][j-t[i]-k]+getFish(i,k) },k表示在第i个湖停留k时间。

程序要特别注意循环变量的边界条件。郁闷的是居然PE了两次……

另外,这个题目在刘汝佳的黑书上有讲,方法是枚举+贪心,效率比动态规划高很多。
/*
ZJU1161 Gone Fishing
*/

#include
#include

#define N 30
#define M 400
#define clr(a) memset(a,0,sizeof(a))
#define MIN(a,b) ((a)>(b)?(b):(a))
#define MAX(a,b) ((a)>(b)?(a):(b))

int n,m;
int f
,d
,t
;
int reach
;
int dp
[M];
int ans
;

int max,mi,mj;
int g
[M];

int getFish(int lake,int time){
if(d[lake])
time = MIN(time , f[lake]/d[lake]+(f[lake]%d[lake]!=0));
if(time==0) return 0;
return f[lake]*time - d[lake]*(time*(time-1)/2);
}

void getAns(int i,int j){
ans[i]=g[i][j];
if(i>1)
getAns(i-1,j-g[i][j]-t[i]);
}

int main()
{
int T,h;

scanf("%d",&T);
while(T--){
int newLine=0;
while(scanf("%d",&n),n){
//init
clr(f); clr(d); clr(t);
clr(dp); clr(g); clr(ans);

//input
int i,j,k;
scanf("%d",&h);
m=h*12;
for(i=1;i<=n;i++) scanf("%d",&f[i]);
for(i=1;i<=n;i++) scanf("%d",&d[i]);
for(i=2;i<=n;i++) scanf("%d",&t[i]);
reach[1]=0;
for(i=2;i<=n;i++) reach[i]=t[i]+reach[i-1];

//DP
max=0;
for(j=0 ;j<=m;j++){
dp[1][j] = getFish(1,j);
if(max<=dp[1][j]){
max = dp[1][j];
mi=1; mj=j;
}
g[1][j]=j;
}

int num;
for(i=2;i<=n;i++){
for(j=m;j>=reach[i];j--){
dp[i][j]=-1;
for(k=0;k<=j-reach[i];k++){
num=dp[i-1][j-t[i]-k]+getFish(i,k);
if(num>dp[i][j]){
dp[i][j]=num;
g[i][j]=k;
}
}
if(max
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: