POJ 2385 Apple Catching DP

简单DP

用dp[i][j]表示第i个苹果掉落,刚好走了j步能吃到苹果的最大值

读入时把两颗树的标号1,2处理成0,1,以下说的树的编号都是处理后的0,1;

用num[i][2]来记录第i个秒掉落在两颗数的苹果个数,掉落在树0,则num[i][0]=1,num[i][1]=0,掉落在树1,则num[i][1]=1,num[i][0]=0;(num[]数组记得初始化);

dp[][]数组初始值:

 if(num[1][0]==1)dp[1][0]=1;
 dp[1][1]=1;

状态转移:

当j=0时,dp[i][j]的前一个状态只能是原地不动(且一定在树0位置)dp[i-1][j],所以dp[i][j]=dp[i-1][j]+num[i][0](num[i][0]表示第i秒掉路在树0的苹果数);
当j!=0时,根据j的奇偶性可以判断走到了哪一棵树,走到了树(j&1)。dp[i][j]的前的状态有2个:

状态1:没有移动dp[i-1][j];

状态2:移动了dp[i-1][j-1];

状态转移方程为:

if(j==0)dp[i][j]=dp[i-1][j]+num[i][0];
               
else dp[i][j] = max(dp[i-1][j],dp[i-1][j-1])+num[i][j&1];

最后枚举所有dp[n][i](i表示步数),求其中的最大值。

AC代码:

View Code
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int dp[1003][34];
int num[1003][2];
int n,m;
int main()
{
    int i, j, tmp;
    while(~scanf("%d%d",&n,&m))
    {
        memset(num,0,sizeof(num));
        for(i=1;i<=n;i++)
        {
            scanf("%d",&tmp);
            num[i][tmp-1]++;
        }
        memset(dp,0,sizeof(dp));
        if(num[1][0]==1)dp[1][0]=1;
        dp[1][1]=1;
        for(i=2;i<=n;i++)
        {
            for(j=0;j<=m;j++)
            {
                if(j==0)dp[i][j]=dp[i-1][j]+num[i][0];
                else dp[i][j] = max(dp[i-1][j],dp[i-1][j-1])+num[i][j&1];
            }
        }
        int ans=0;
        for(i=0;i<=m;i++)
            ans = max(ans,dp[n][i]);
        printf("%d\n",ans);
    }
    return 0;
}

 

 

posted @ 2012-08-06 19:11  To be an ACMan  Views(226)  Comments(0)    收藏  举报