1. 程式人生 > >【題解】Luogu P2690 接蘋果

【題解】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;
}