【题解】Luogu P2690 接苹果

题目描述

这道题以时间为阶段,是一道很明显的线性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;
}

猜你喜欢

转载自blog.csdn.net/kcn999/article/details/84888845
今日推荐