题意
现在有两棵树,在1~t分钟内,其中一棵树会掉落一个苹果。一开始你在第一棵树下,每次你只能接住当前在的那棵树上掉落的苹果,或者花费1个体力点瞬移到另一棵树下,接住那个苹果。你总共有w个体力点。给定t,w,每分钟苹果的掉落情况,问你最多能获得多少个苹果。
分析
状态定义为 dp[i][j]:前t分钟在花费j个体力点的情况下能获得的最多苹果数。
状态转移方程 dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+(i分钟时当前树下是否掉落苹果). 当前状态有两个限制条件,一个是时间,另一个是移动的次数也就是花费的体力点。因此这一分钟的情况只能是上一分钟的情况转移过来。如果前一分钟没有移动那么也就还是这棵树,就是dp[i-1][j]+当前树是否掉落苹果;如果前一分钟是另一棵数,则表示要花费一个体力点,那么现在是j的话前一分钟就是j-1,所以就是dp[i-1][j-1]。最后一个问题是怎么判断当前是哪一棵树,因为每次只能从一棵树跳到另一棵,所找规律可以发现如果跳的奇数次就跳回来了,也就是最开始的第一棵树,然后偶数次就是另一棵。还要注意一点,边界判断,具体看代码
代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[1005][35];
int a[1005];
int main()
{
int t, w;
while (cin >> t >> w)
{
int p;
memset(a, 0, sizeof(a));
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= t; i++)
cin >> a[i];
for (int i = 1; i <= t; i++)
{
for (int j = 0; j<=w; j++)
{
//注意判断边界
if (j > 0)dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]);
else dp[i][j] = dp[i - 1][j];
if (j % 2 + 1 == a[i])
dp[i][j]++;
}
}
int ans = dp[t][0];
for (int i = 1; i <= w; i++)
ans = max(ans, dp[t][i]);
cout << ans << endl;
}
return 0;
}