首页 > 代码库 > NOJ1060 接苹果 二维DP
NOJ1060 接苹果 二维DP
题目描述
很少有人知道奶牛爱吃苹果。农夫约翰的农场上有两棵苹果树(编号为1和2), 每一棵树上都长满了苹果。奶牛贝茜无法摘下树上的苹果,所以她只能等待苹果 从树上落下。但是,由于苹果掉到地上会摔烂,贝茜必须在半空中接住苹果(没有人爱吃摔烂的苹果)。贝茜吃东西很快,她接到苹果后仅用几秒钟就能吃完。每一分钟,两棵苹果树其中的一棵会掉落一个苹果。贝茜已经过了足够的训练, 只要站在树下就一定能接住这棵树上掉落的苹果。同时,贝茜能够在两棵树之间 快速移动(移动时间远少于1分钟),因此当苹果掉落时,她必定站在两棵树其中的一棵下面。此外,奶牛不愿意不停地往返于两棵树之间,因此会错过一些苹果。苹果每分钟掉落一个,共T(1<=T<=1000)分钟,贝茜最多愿意移动W(1<=W<=30) 次。现给出每分钟掉落苹果的树的编号,要求判定贝茜能够接住的最多苹果数。 开始时贝茜在1号树下。
输入
第一行2个数,t和k。接下来的t行,每行一个数,代表在时刻t苹果是从1号苹果树还是从2号苹果树上掉下来的。
输出
对于每个测试点,输出一行,一个数,为奶牛最多接到的苹果的数量。
输入样例
7 2
2
1
1
2
2
1
1
输出样例
6(输出注解:贝茜不移动直到接到从第1棵树上掉落的两个苹果,然后移动到第2棵树下,直到接到从第2棵树上掉落的两个苹果,最后移动到第1棵树下,接住最后两个从第1 棵树上掉落的苹果。这样贝茜共接住6个苹果。)
解题思路
这是一题二维DP 我们用dp[i][j]表示到前i个苹果,换了j次的最大苹果数量。
假设我们现在已经考虑完了i-1的情况。
那么如果第i个苹果我们移动:有dp[i][j] = dp[i-1][j-1] + 当前位置是否有苹果(0或1)
如果第i个苹果我们不移动:有dp[i][j] = dp[i-1][j] + 当前位置是否有苹果(0or1)
(当前位置:换了j次 如果j是奇数 那么奶牛肯定在2号树 如果j是偶数 那么奶牛肯定是在1号树)
下面我们考虑一下dp的初始化。做了几道DP问题之后我发现DP问题最难的地方在建立DP数组 而最需要小心的地方则是DP数组的初始化,这题就跳进了一个陷阱。。。幸好及时发现了。
从状态转移方程我们知道要初始化dp[x][0]和dp[1][x]
dp[x][0] 即不移动 一直在1号树下面 能接到多少自己脑补。。。
dp[1][x]即只考虑第一个苹果 奶牛在下面移来移去。。。自己脑补
下面放代码
#include <cstdio> #include <cstring> #include <algorithm> const int maxpingguo= 1010; const int maxyidong = 35; using namespace std; int dp[maxpingguo][maxyidong]; int apple[maxpingguo][3];//apple[i][j]=1为在第i分钟j树上有苹果 这样设计apple数组为下面的DP创造方便 int main() { int pingguo,yidong; scanf("%d%d",&pingguo,&yidong); for(int i = 1 ; i <= pingguo ; i ++) { int t; scanf("%d",&t); apple[i][t] = 1; } //dp初始化 for(int i = 1 ; i <= yidong ; i ++) { if(i%2) { if(apple[1][2]) dp[1][i] = 1; else dp[1][i] = 0; }else { if(apple[1][1]) dp[1][i] = 1; else dp[1][i] = 0; } } for(int i = 1 ; i <= pingguo ; i ++) {/*这里有一个陷阱,一开始我觉得上面已经初始化过dp[1][1]了 所以直接从i=2走起了 *但实际上如果yidong=0的情况下上面的初始化并不会执行!! */ dp[i][0] = dp[i-1][0] +apple[i][1]; } //dp for(int j = 1 ; j <= yidong ; j ++) { for(int i = 2 ; i <= pingguo ; i ++) { if(j%2) { dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]) +apple[i][2]; }else { dp[i][j] = max(dp[i-1][j],dp[i-1][j-1]) +apple[i][1]; } } } int _max = -1; for(int i = 0 ; i <= yidong ; i ++) { if(_max < dp[pingguo][i]) _max = dp[pingguo][i]; } printf("%d\n",_max); return 0; }
NOJ1060 接苹果 二维DP