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


浙公网安备 33010602011771号