/*
poj2385 2016.4.24 14:49
题意:有两棵苹果树,t分钟其中一棵会掉一个苹果,一个人开始时站在树0下,可以在两棵苹果树间最多移动w次,求这个人最多可以吃到的苹果数量。
题解:dp[t][w][x]表示第t分钟在苹果树x下,且已经最多移动了w次,注意是最多,不一定是刚好移动了w次。
那么转移方程是
对于当前第i分钟,掉的苹果在树val[i]:
1. 当前第i分钟时,我刚好在val[i]树下,可以得到一个苹果。考虑其由来:
1.1 i - 1分钟在val[i], 不需要移动。
dp[i - 1][j][val[i]] + 1,还是j。
1.2 i - 1分钟在1 - val[i]则需要移动一步,才能吃到该苹果。
dp[i - 1][j - 1][1 - val[i]] + 1,消耗一步,前一分钟最多只能移动j - 1步。
2. 当前第i分钟,我刚好在1 - val[i]树下,同样考虑其由来,则
2.1 i - 1分钟在1 - val[i]下,不需要移动,继续等。
dp[i - 1][j][1 - val[i]]
2.2 i - 1分钟在val[i]下,需要移动一步,到树1 - val[i]
dp[i - 1][j - 1][val[i]]
上面两种情况都要考虑,即dp[i][j][0]和dp[i][j][1]
例子:两分钟,最多只能走一步,且第一分钟是树0,然后是树1
2, 1
0 1
考虑初始状态,即零分钟的情况:
dp[0][0][0] = dp[0][1][0] = 0,可以,零分钟时在树0不移动,没有吃到苹果。
dp[0][0][1] = dp[0][1][1] = -1,起始时在树0,不在树1,不合法。
运算:
1.1
1分钟最多走0步,在树0,且掉落的苹果在树0
dp[1][0][0] = max(dp[0][0][0](0), dp[0][-1][1](越界不考虑,视为-1)) + 1 = 1
在树1,没有掉苹果,不加一
dp[1][0][1] = max(dp[0][0][1](-1,非法), dp[0][-1][0](-1)) = -1,同时非法(-1),则视为非法
1.2
1分钟,最多走一步,在树1,相当于没走
dp[1][1][0] = max(dp[0][1][0](0), dp[0][0][1](-1)) + 1 = 1
从树0到树1,但在树0掉落...
dp[1][1][1] = max(dp[0][1][1](-1), dp[0][0][0](0)) = 0
2.1
2分钟,树1掉苹果。不走,在树0,相当于前2分钟都在树0,只等到一个苹果,不走...
dp[2][0][0] = max(dp[1][0][0](1), dp[1][-1][1](-1)) = 1
不走,然后在树1,是不可能的...
dp[2][0][1] = max(dp[1][0][1](-1), dp[1][-1][0](-1)) + 1 = -1
2.2
赖在树0不走
dp[2][1][0] = max(dp[1][1][0](1), dp[1][0][1](-1)) = 1
0分钟时移到树1一直等候,没吃到树0的苹果,吃到树1的苹果,或者1分钟在树0等候,然后2分钟移到树1等候,然后吃到两个苹果...
dp[2][1][1] = max(dp[1][1][1](0), dp[1][0][0](1)) + 1 = 2
结果就是max(dp[2][1][0], dp[2][1][1]) = 2
*/
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int MAX_T = 3000 + 10, MAX_W = 30 + 10;
int dp[MAX_T][MAX_W][2], val[MAX_T];
int main(){
int t, w, i, j, k;
//freopen("in.txt", "r", stdin);
scanf("%d%d", &t, &w);
for(i = 1; i <= t; i++){
scanf("%d", &val[i]);
val[i]--;
}
for(i = 0; i <= w; i++){
dp[0][i][0] = 0;
dp[0][i][1] = -1;
}
for(i = 1; i <= t; i++){
for(j = 0; j <= w; j++){
dp[i][j][val[i]] = -1;
dp[i][j][1 - val[i]] = -1;
if(dp[i - 1][j][val[i]] != -1){
dp[i][j][val[i]] = max(dp[i][j][val[i]], dp[i - 1][j][val[i]] + 1);
}
if(j >= 1 && dp[i - 1][j - 1][1 - val[i]] != -1){
dp[i][j][val[i]] = max(dp[i][j][val[i]], dp[i - 1][j - 1][1 - val[i]] + 1);
}
dp[i][j][1 - val[i]] = max(dp[i][j][1 - val[i]], dp[i - 1][j][1 - val[i]]);
if(j >= 1){
dp[i][j][1 - val[i]] = max(dp[i][j][1 - val[i]], dp[i - 1][j - 1][val[i]]);
}
}
}
printf("%d\n", max(dp[t][w][0], dp[t][w][1]));
return 0;
}
poj2385 动态规划
最新推荐文章于 2019-07-13 11:51:00 发布