题意:有两个树(树1, 树2),每分钟其中一棵树就会掉落一个苹果,会掉下来 T 个(1分钟掉下1个),你可以有 W 次机会选择站在那个树下,开始没在任何树下。
思路:dp[i][j][2] 意味着前i 个 苹果落下, 前 j 次移动 的 最大值(i <= T, j <= W);
dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j-1][1]) + tree[0];
dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0]) + tree[1];
代码分析:
如果第 i 个 苹果 在 树1 落下 tree[0] = 1, tree[1] = 0; 反之 tree[0] = 0, tree[1] = 0;
每一个值更新有两种情况:
dp[i][j][0] 第 i 个苹果, 第 j 次 移动 , 站在 树 1 下;
上个苹果站在这个树下 dp[i-1][j][0], 上个苹果在另外一个树下dp[i-1][j-1][1] 。
dp[i][j][1] 第 i 个苹果, 第 j 次 移动 , 站在 树 1 下;
上个苹果站在这个树下 dp[i-1][j][1], 上个苹果在另外一个树下dp[i-1][j-1][0] 。
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int dp[1010][35][2];
int main()
{int pos[1010], n, s, i, j;scanf("%d %d",&n,&s);for(i=1; i<=n; i++)scanf("%d",&pos[i]);memset(dp, 0, sizeof(dp)); // 初始化for(i=1; i<=n; i++){int tree[2];// 如果第 i 个苹果在树 1 落下 tree[0] = 1,tree[1] = 0;反之 tree[0] = 0,tree[1] = 0;if(pos[i] == 1){tree[0]=1;tree[1]=0;}else{tree[0]=0;tree[1]=1;}dp[i][0][0] = dp[i-1][0][0] + tree[0];dp[i][0][1] = dp[i-1][0][1] + tree[1];for(j=1; j<=s; j++){dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j-1][1]) + tree[0];dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0]) + tree[1];}}int ans;ans = max(dp[n][s][0],dp[n][s][1]);printf("%d\n",ans);return 0;
}