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;
}