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;

}

  

posted @ 2012-01-16 17:57  快乐.  阅读(458)  评论(0编辑  收藏  举报