poj 2385 Apple Catching(记录结果再利用的动态规划)
https://www.cnblogs.com/violet-acmer/p/9852294.html
题意:
有两颗苹果树,在每一时刻只有其中一棵苹果树会掉苹果,而Bessie可以在很短的时间内在两个苹果树间切换,但每一时刻只能切换一下;
求在1~T时刻,Bessie在最多可以切换W次的前提下最多可以获得多少苹果?
题解:
定义变量dp[ i ][ j ] : 前 i 时刻,移动 j 步所获得的最大的苹果数量;
据此写出状态转移方程:
如何判断在i处是否的到苹果呢?
①如果dp[i-1][ j-1]为偶数,那么在 i 处移动之前,Bessie应该在 2 号苹果树下,因为在 i 处移动了,Bessie是在 1 号苹果树下等待 i 时刻的苹果
反之,Bessie是在 2 号苹果树下等待 i 时刻的苹果。
②如果dp[i-1][ j ]为偶数,且Bessie在 i 时刻并没有移动,所以Bessie是在 2 号苹果树下等待 i 时刻的苹果
反之,Bessie是在 1 号苹果树下等待 i 时刻的苹果。
poj维护中............之前交的代码本地没保存,现在不想写了,明天看看poj还能登陆吗。。。。。啊啊啊啊
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define mem(a,b) memset(a,b,sizeof(a)) 7 const int maxn=1e3+10; 8 9 int T,W; 10 int tree[maxn];//tree[i]=1/2 : i时刻果树1/2掉苹果 11 int dp[maxn][40]; 12 13 int inOne(int i){//判断i时刻果树1是否掉苹果 14 return tree[i] == 1 ? 1:0; 15 } 16 int inTwo(int i){//判断i时刻果树2是否掉苹果 17 return tree[i] == 2 ? 1:0; 18 } 19 int walk(int i,int j)//在i时刻移动 20 { 21 if((j-1)&1) 22 return dp[i-1][j-1]+inOne(i); 23 return dp[i-1][j-1]+inTwo(i); 24 } 25 int noWalk(int i,int j)//在i时刻不移动 26 { 27 if(j&1) 28 return dp[i-1][j]+inTwo(i); 29 return dp[i-1][j]+inOne(i); 30 } 31 void Solve() 32 { 33 mem(dp,0); 34 for(int i=1;i <= T;++i)//i时刻 35 for(int j=0;j <= W;++j)//前i时刻共移动j步 36 if(j == 0) 37 dp[i][j]=dp[i-1][j]+inOne(i); 38 else 39 dp[i][j]=max(walk(i,j),noWalk(i,j)); 40 printf("%d\n",*max_element(dp[T]+0,dp[T]+W+1)); 41 } 42 int main() 43 { 44 scanf("%d%d",&T,&W); 45 for(int i=1;i <= T;++i) 46 scanf("%d",tree+i); 47 Solve(); 48 }