这道题以时间为阶段,是一道很明显的线性dp。
这道题有一个要点: 因为只有两棵树且初始为第一棵树下,所以移动奇数次到达第二颗树,移动偶数次则到达第一棵树。
理解这个时候就可以直接推出状态转移方程了。
具体可以看下面的代码来理解。
#include <iostream>
#define MAX_N 31
using namespace std;
int t, n;
int dp[MAX_N]; // 移动了i次后的苹果最优方案,这里运用了滚动数组
int ans;
int main()
{
cin >> t >> n;
int v;
for(register int i = 1; i <= t; ++i)
// 第i分钟
{
cin >> v;
for(register int j = min(i, n) - ((v & 1) == (min(i, n) & 1)); j >= 0; j -= 2)
// 第j次移动时到达当前这棵树v
// min(i, n):因为当i < n时,最多只有i次移动,所以就这么求最小值
// & 1可以理解为 % 2
// 如果当前树的编号的奇偶性与最多移动次数n的奇偶性相同,就最多只能移动(n - 1)次从而回到当前这棵树,具体可以自己带入数据验证
// j -= 2: 因为要再移动2次才能回到当前的树,所以就- 2
{
if(j) dp[j] = max(dp[j], dp[j - 1]) + 1;
// 如果j不为0,那么就可以从原地不动和从第j-1次移动到另一棵树后在移动回这一棵树中的最优方案
else ++dp[j];
// 如果j为0,那么就代表无法移动,所以就只能在最开始的第一棵树捡苹果(j = 0时v就为1)。
}
}
for(register int i = 0; i <= n; ++i)
{
ans = max(ans, dp[i]);
}
cout << ans;
return 0;
}