POJ 1042 贪心 DP(钓鱼问题)
http://poj.org/problem?id=1042
被这个题虐的一塌糊涂啊,时间有两个世纪那么长
有DP和贪心两种解法
下面DP
状态转移方程 dp[i][j]=Max(dp[i][j],dp[i-1][j-ti[i]-k]), 但是因为memset(dp,-1,sizeof(dp)),
所以写的时候是 dp[i+1][j+K+ti[i]]=Max(dp[i][j]+sum,dp[i+1][j+k+ti[i]);
DP代码:
#include<iostream>
#include<string>
#include<cstring>
#include <cmath>
#include<cstdio>
#include<algorithm>
#define Max(a,b) a>b?a:b;
using namespace std;
int ti[30],fi[30][400],di[30],dp[30][400];
int h ,n,i,j,k;
int main()
{
while(~scanf("%d",&n)&&n)
{
memset(fi,0,sizeof(fi));
scanf("%d",&h);
h=h*12;//共h个五分钟
for(i=1;i<=n;i++)//i=1
scanf("%d",&fi[i][1]);
for(i=1;i<=n;i++)
scanf("%d",&di[i]);
for(i=2;i<=n;i++)//i=2
scanf("%d",&ti[i]);
ti[1]=0;
for(i=1;i<=n;i++)
{
for(k=2;k<=h;k++)
{
if(fi[i][k-1]<=di[i])break;
fi[i][k]=fi[i][k-1]-di[i];
}
}
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
int sum,tt=0;
for(i=0;i<n;i++)
{
for(j=0;j<=h;j++)
{ sum=0;
for(k=0;k<=h&&dp[i][j]!=-1;k++)//!!!**没想到这小细节还是关键来
{
if(j+ti[i+1]+k>h)break;
dp[i+1][j+ti[i+1]+k]=Max(dp[i][j]+sum,
dp[i+1][j+ti[i+1]+k]);
if(fi[i+1][k+1]>0)
sum+=fi[i+1][k+1];
}
}
}
int mark=1,MAX=0;
for(i=1;i<=n;i++)
{
if(MAX<dp[i][h])
{
MAX=dp[i][h];
mark=i;
}
}
//cout<<"MAX="<<MAX<<endl;
int MMAX=MAX;
for(i=mark;i>=2;i--)
{
int sum=0;
for(k=0;k<=h;k++)
{
if(MAX==sum+dp[i-1][h-k-ti[i]])
{
fi[i][0]=k;
break;
}
sum=sum+fi[i][k+1];
}
h=h-ti[i]-k;
MAX-=sum;//开始漏了
}
fi[1][0]=h;
for(i=1;i<n;i++)
printf("%d, ",fi[i][0]*5);
printf("%d\n",fi[i][0]*5);
printf("Number of fish expected: %d\n\n",MMAX);
}
return 0;
}
枚举+贪心
运行速度竟然比DP快
代码:
#include<iostream> #include<string> #include<cstring> #include<cstdio> using namespace std; int fi[30],gi[30],di[30],ti[30]; int time[30],TIME[30]; int main() { int n,h,H,i,j,k,MAX,mark,MARK,maxx,SUM; while(~scanf("%d",&n)&&n) { scanf("%d",&h); h=h*12; for(i=1;i<=n;i++) scanf("%d",&fi[i]); for(i=1;i<=n;i++) scanf("%d",&di[i]); for(i=2;i<=n;i++) scanf("%d",&ti[i]); MAX=0;//最后的最大值 memset(TIME,0,sizeof(TIME));//最后的时间 TIME[1]=h; MARK=1;//记录第k个岛 for(k=1;k<=n;k++) { SUM=0;//记录前K个岛钓到鱼的总数 H=h; for(i=2;i<=k;i++) H-=ti[i]; if(H<=0)break; memset(time,0,sizeof(time)); for(i=1;i<=k;i++) gi[i]=fi[i]; while(H>0) { //贪心 找最大的 maxx=gi[1]; mark=1; for(j=2;j<=k;j++) { if(gi[j]>maxx) { maxx=gi[j]; mark=j; } } if(gi[mark]>di[mark]) { gi[mark]-=di[mark]; } else gi[mark]=0; time[mark]++; SUM+=maxx; H--; } if(MAX<SUM) { MAX=SUM; for(i=1;i<=k;i++) TIME[i]=time[i]; MARK=k; } } for(i=1;i<n;i++) printf("%d, ",TIME[i]*5); printf("%d\n",TIME[i]*5); printf("Number of fish expected: %d\n\n",MAX); } return 0; }