DP 之 poj 2385
// [3/24/2014 Sjm]
/*
先模拟一下测试用例:
时间 掉苹果的那棵树 对应时间下在跑了 w 次的情况下获得苹果的最大值
w = 0(在1处) 1(在2处) 2(在1处)
Bessie 在哪里,就说明哪里的苹果可接
1 2 0 1 0
2 1 1 1 2
3 1 2 1 3
4 2 2 3 3
5 2 2 4 3
6 1 3 4 5
7 1 4 4 6
定义: dp[i+1][j+1] := 在i+1的时间时,在跑了 j+1 次的情况下获得苹果的最大值
在考虑第 i+1 的时间点,已跑 j+1 次时,
分析:
1) 第 i 的时间点时,已跑 j 次: 若在第 i+1 的时间点,再跑一次,即 j+1 次时,判断可否接到苹果;
2) 第 i 的时间点时,已跑 j+1 次: 若在第 i+1 的时间点,原地静止,判断可否接到苹果;
(两者取最大值即答案)
综上: dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i][j]) + ((接到苹果) ? 1 : 0);
// 以下在 poj 上似乎没有被考虑(当然也可能我考虑错了),因为直接输出 dp[T][W] 亦可 AC
注:
当在 T(即最大时间) 跑 j (0<=j<W)时, 亦可能取到最大值,并非一定是当在 T(即最大时间) 跑 W(即最多次数时) 次时,取得最大值。
例如测试数据:3 1211正确答案应是2 (dp[3][0]取得),而非1 (dp[3][1]取得)。
*/
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 const int MAX_T = 1000, MAX_W = 30; 7 int T, W, myT[MAX_T + 1], myW[MAX_W + 1], dp[MAX_T + 1][MAX_W + 1]; 8 9 int Solve() 10 { 11 for (int i = 0; i < T; i++) 12 for (int j = 0; j < W; j++) 13 dp[i + 1][j + 1] = max(dp[i][j + 1], dp[i][j]) + ((myT[i+1] == myW[j+1]) ? 1 : 0); 14 int myMax = dp[T][0]; 15 for (int i = 1; i <= W; i++) 16 myMax = max(myMax, dp[T][i]); 17 return myMax; 18 } 19 20 int main() 21 { 22 //freopen("input.txt", "r", stdin); 23 //freopen("output.txt", "w", stdout); 24 scanf("%d%d", &T, &W); 25 for (int i = 0; i <= W; i++) 26 myW[i] = ((i & 1) ? 2 : 1); 27 for (int i = 1; i <= T; i++) 28 scanf("%d", &myT[i]); 29 for (int i = 1; i <= T; i++) 30 dp[i][0] = dp[i - 1][0] + ((myT[i] == myW[0]) ? 1 : 0); 31 printf("%d\n", Solve()); 32 return 0; 33 }