【题目大意】
有两棵树1和2,奶牛Bessie位于树1下,每个单位时间会有一个苹果从其中一棵树掉下来,同时Bessie也可以移动一次,但是Bessie不希望移动超过W次,问T时间内Bessie最多得到多少个苹果。
【思路】
经典的动态规划,预处理时将树1和树2分别用0和1来表示。由于移动偶数次可以回到树1,移动奇数次可以回到树2,移动j次时,若j%2==a[i]就表明当前位置恰好有苹果落下。
设f[i][j]为第i个苹果掉下来的时候,移动至多j次可以得到的最多苹果。f[i][j]由f[i-1][j]和f[i-1][j-1]转移过来,对于f[i-1][j-1]又分为当前移动和不移动两种情形。
如果之前已经跑了j次,不动的情况下苹果恰好又掉下来就加一,f[i-1][j]+(j%2==a[i]);
如果之前已经跑了j-1次,再跑动一次,此时恰好苹果掉下来就加一,f[i-1][j-1]+(j%2==a[i]);
果之前已经跑了j-1次,这次不跑动,此时恰好苹果掉了下来就加一,f[i-1][j-1]+((j-1)%2==a[i])。
以上三种情况就可组成状态转移方程。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 using namespace std; 6 const int MAXNt=1000+50; 7 const int MAXNw=30+5; 8 int t,w; 9 int a[MAXNt]; 10 int f[MAXNt][MAXNw]; 11 /*f[i][j]表示第i个苹果掉下来,且跑动了j次的时候能够抓到的最多苹果数*/ 12 13 int main() 14 { 15 scanf("%d%d",&t,&w); 16 17 memset(f,0,sizeof(f)); 18 f[0][0]=0; 19 /*第零个苹果掉落下来的时候,移动零次最多得到零个苹果*/ 20 for (int i=1;i<=t;i++) 21 { 22 scanf("%d",&a[i]); 23 f[i][0]=f[i-1][0]+(a[i]==1); 24 /*如果当前站在第一棵树的下面,那么不动的情况下可以多抓到一个苹果*/ 25 a[i]--; 26 /*将站爱第一棵树下的设为0,站在第二课树下的设为1*/ 27 } 28 29 for (int i=1;i<=t;i++) 30 for (int j=1;j<=w;j++) 31 { 32 f[i][j]=max(f[i][j],f[i-1][j]+(j%2==a[i])); 33 /*如果之前已经跑了j次,不动的情况下苹果恰好又掉下来,则加1*/ 34 f[i][j]=max(f[i][j],f[i-1][j-1]+(j%2==a[i])); 35 /*如果之前已经跑了j-1次,再跑动一次,此时恰好苹果掉下来,则加1*/ 36 f[i][j]=max(f[i][j],f[i-1][j-1]+((j-1)%2==a[i])); 37 /*如果之前已经跑了j-1次,这次不跑动,此时恰好苹果掉了下来,则加1*/ 38 } 39 cout<<f[t][w]<<endl; 40 return 0; 41 }