【题解】「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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章