【題解】「USACO2008MAR」River Crossing(DP)

題面

【題目描述】
FarmerFarmer JohnJohn以及他的N(1<=N<=2,500)N(1 <= N <= 2,500)頭奶牛打算過一條河,但他們所有的渡河工具,僅僅是一個木筏。
由於奶牛不會划船,在整個渡河過程中,FJFJ必須始終在木筏上。在這個基礎上,木筏上的奶牛數目每增加11FJFJ把木筏劃到對岸就得花更多的時間。 當FJFJ一個人坐在木筏上,他把木筏劃到對岸需要M(1<=M<=1000)M(1 <= M <= 1000)分鐘。當木筏搭載的奶牛數目從i1i-1增加到ii時,FJFJ得多花Mi(1<=Mi<=1000)M_i(1 <= M_i <= 1000)分鐘才能把木筏劃過河(也就是說,船上有11頭奶牛時,FJFJ得花M+M1M+M_1分鐘渡河;船上有22頭奶牛時,時間就變成M+M1+M2M+M_1+M_2分鐘。後面的依此類推)。那麼,FJFJ最少要花多少時間,才能把所有奶牛帶到對岸呢?當然,這個時間得包括FJFJ一個人把木筏從對岸劃回來接下一批的奶牛的時間。
【輸入】
第一行兩個整數數N,MN,M,表示NN頭奶牛和FJFJ獨自劃到對岸的時間;
接下來NN個數,爲MiM_i
【輸出】
一個整數,最少時間。
【樣例輸入】

5 10 
3 
4 
6 
100 
1

【樣例輸出】

50

【樣例解釋】
FJFJ第一次帶33頭牛過河,一共花費10+3+4+6=2310+3+4+6=23分鐘,然後一個人劃回來,花費1010分鐘,最後帶剩下的22頭牛過河,花費10+3+4=1710+3+4=17分鐘,總共23+10+17=5023+10+17=50分鐘。

算法分析

對於DPDP,最簡單的狀態就是問題怎麼問,怎麼設。
狀態:
f[i]f[i]——運輸ii頭牛過河花費的最少時間。

狀態轉移方程:
總共運輸ii頭牛,考慮當前這一次運輸了幾頭牛,設當前這一次運輸jj頭牛。數組sumsum存放MiM_i.
f[i]=minf[i]=min{ f[ij]+sum[j]+2mf[i-j]+sum[j]+2*m },1<=i<=n,1<=j<=i1<=i<=n,1<=j<=i。

最後的答案就是f[n]mf[n]-mFJFJ運輸最後一次不會返回)。
時間複雜度:O(n2)O(n^2)

參考程序

#include<iostream>
#include<cstring> 
#include<cstdio> 
#define N 3000 
using namespace std;
int f[N],sum[N];
int main()
{
    int n,m;
    cin>>n>>m;
    int a;
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        sum[i]=sum[i-1]+a;
    }
    for(int i=1;i<=n;i++)
    {
        int minn=N*10000;
        for(int j=1;j<=i;j++)	//當前這一次運輸j頭牛
            minn=min(minn,f[i-j]+sum[j]+2*m);
        f[i]=minn;
    }
    cout<<f[n]-m<<endl;     //送完了就不用會來了 
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章