【題解】「USACO2004NOV」Apple Catching(DP)

題面

【題目描述】
很少有人知道奶牛愛喫蘋果.農夫約翰的農場上有兩棵蘋果樹(編號爲1122),每一棵樹上都長滿了蘋果.奶牛貝茜無法摘下樹上的蘋果,所以她只能等待蘋果從樹上落下.但是,由於蘋果掉到地上會摔爛,貝茜必須在半空中接住蘋果(沒有人愛喫摔爛的蘋果).貝茜喫東西很快,所以她接到蘋果後僅用幾秒鐘就能喫完.每一分鐘,兩棵蘋果樹其中的一棵會掉落一個蘋果.貝茜已經過了足夠的訓練,只要站在樹下就一定能接住這棵樹上掉落的蘋果.同時,貝茜能夠在兩棵樹之間快速移動(移動時間遠少於1分鐘),因此當蘋果掉落時,她必定站在兩棵樹其中的一棵下面.此外,奶牛不願意不停地往返於兩棵樹之間,因此會錯過一些蘋果, 蘋果每分鐘掉落一個,共T(1T1000)T(1≤T≤1000)分鐘,貝茜最多願意移動W(Iw30)W(I≤w≤30)次.
現給出每分鐘掉落蘋果的樹的編號,要求判定貝茜能夠接住的最多蘋果數.開始時貝茜在11號樹下.
【輸入】
11行:由空格隔開的兩個整數TTWW.
22T+1T+1行:1122(每分鐘掉落蘋果的樹的編號).
【輸出】
在貝茜移動次數不超過W的前提下她能接到的最多蘋果數
【樣例輸入】

7 2
2
1
1
2
2
1
1

【樣例輸出】

6

【樣例解釋】
77分鐘內共掉落77個蘋果一一第11個從第22棵樹上掉落,接下來的22個蘋果從第11棵樹上掉落,再接下來的22個從第22棵樹上掉落,最後22個從第11棵樹上掉落.
貝茜不移動直到接到從第11棵樹上掉落的兩個蘋果,然後移動到第22棵樹下,直到接到從第22棵樹上掉落的兩個蘋果,最後移動到第11棵樹下,接住最後兩個從第11棵樹上掉落的蘋果.這樣貝茜共接住66個蘋果.

算法分析

我們需要知道貝西當前在在一棵樹下,使用了多少次移動次數,當前的時間。那麼就定義一個數組表示這些信息:

狀態:
f[t][i][j]f[t][i][j]——tt分鐘,移動ii次,此時在第jj棵樹下得到的最多蘋果數。

狀態轉移方程:
考慮第ii分鐘時,是否進行移動,移動到哪一棵樹下。
爲了寫代碼方便,使用數組a[0][t]a[0][t]表示tt分鐘第11棵蘋果樹掉落的蘋果,a[1][t]a[1][t]表示tt分鐘第22棵蘋果樹掉落的蘋果,當前在第jj棵蘋果樹下,移動就會移動到第(j+1)%2(j+1)\%2棵蘋果數下。
分兩種情況:
不移動:f[t][i][j]=f[t1][i][j]+a[j][t]f[t][i][j]=f[t-1][i][j]+a[j][t](1<=t<=T0<=i<=W)(1<=t<=T,0<=i<=W)
移動:f[t][i][j]=f[t1][i1][(j+1)%2]+a[(j+1)%2][t]f[t][i][j]=f[t-1][i-1][(j+1)\%2]+a[(j+1)\%2][t]
取一個maxmax值。
時間複雜度:O(TW)O(TW)

參考程序

#include<bits/stdc++.h>
#define N 1010
using namespace std;
int n,m;
int a[2][N];    //a[0]爲第一棵樹,a[1]爲第二棵樹 
int f[N][33][2];    //f[t][i][j],t分鐘,移動i次,在第j棵樹下 
int main()
{
    scanf("%d%d",&n,&m);
    int x;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&x);
        if(x==1) a[0][i]=1;
        else a[1][i]=1;
    }
    int ans=0;
    for(int i=0;i<=m;i++)
        for(int j=0;j<=1;j++)
            f[0][i][j]=0;   
    for(int t=1;t<=n;t++)
        for(int i=0;i<=m;i++)
            for(int j=0;j<=1;j++)
            {
                if(i==0)
                    f[t][i][j]=f[t-1][i][j]+a[j][t];	
                else
                    f[t][i][j]=max(f[t-1][i][j]+a[j][t],f[t-1][i-1][(j+1)%2]+a[(j+1)%2][t]);//不移動或者移動 
                if(t==n) ans=max(f[n][i][j],ans);
            } 
    cout<<ans<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章