洛谷 P2690 [USACO04NOV]Apple Catching G
题目大意:
奶牛喜欢吃苹果。约翰有两棵苹果树,有 N 只苹果会从树上陆续落下。如果掉苹果的时候,贝西在那棵树下,她就能接住苹果。贝西一开始在第一棵树下。在苹果掉落之前,她有足够的时间来回走动,但她很懒,最多只愿意移动 K 次。请计算一下她最多可以接住几只苹果。
分析:
首先很明显这是一道动态规划的问题(一开始脑子抽了做了个背包发现状态转移极为麻烦)。
分析题目,发现决定每一种状态的关键变量仅为 当前的时间 和 跳动的次数。因此,我们建立一个二维的 \(dp[i][j]\),表示当时间为 \(i\),总共跳动了 \(j\) 次的时候能够摘到的最多的果实。
在每一刻时间,我们可以选择转移到另一棵树下,也可以选择不进行转移,这就提示我们每个 \(dp[i][j]\) 可以从 \(dp[i - 1][j]\) 或 \(dp[i - 1][j - 1]\) 转移过来。同时,如果在当前时刻,所在的树上掉落了一个果实,那么我们就可以得到这个果实,答案加一。
综上,我们有如下的状态转移方程:
\[\begin{cases}
dp[i][j] = \max(dp[i - 1][j,dp[i - 1][j - 1]) \\
dp[i][j] += 1 &\text{j % 2 + 1 == a[i]} \\
\end{cases}
\]
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1005;
int n,k,dp[MAXN][MAXN],a[MAXN];
int main(){
cin >> n >> k;
for(int i = 1;i <= n; i++){
cin >> a[i];
}
for(int i = 1; i <= n; i++){
for(int j = 0; j <= k; j++){
if(j == 0)dp[i][j] = dp[i - 1][j];
else dp[i][j] = max(dp[i - 1][j],dp[i - 1][j - 1]);
if(j % 2 + 1 == a[i])dp[i][j]++;
}
}
int ans = 0;
for(int i = 0; i <= k; i++){
ans = max(ans,dp[n][i]);
}
cout << ans;
}