奶牛渡河
题目描述
\(Farmer John\) 以及他的 \(N (1\leq N\leq 2500)\) 头奶牛打算过一条河,但他们所有的渡河工具,仅仅是一个木筏。
由于奶牛不会划船,在整个渡河过程中,\(Farmer John\) 必须始终在木筏上。在这个基础上,木筏上的奶牛数目每增加 \(1\) ,\(Farmer John\) 把木筏划到对岸就得花更多的时间。
当\(Farmer John\) 一个人坐在木筏上,他把木筏划到对岸需要\(M (1\leq M\leq 1000)\)分钟。
当木筏搭载的奶牛数目从 \(i-1\) 增加到 \(i\) 时,\(Farmer John\)得多花 \(M_i (1\leq M_i\leq 1000)\) 分钟才能把木筏划过河。
也就是说,船上有 \(1\) 头奶牛时,\(Farmer John\) 得花 \(M+M_1\) 分钟渡河;船上有 \(2\) 头奶牛时,时间就变成 \(M+M_1+M_2\) 分钟。后面的依此类推。
那么,\(Farmer John\) 最少要花多少时间,才能把所有奶牛带到对岸呢?当然,这个时间得包括 \(Farmer John\) 一个人把木筏从对岸划回来接下一批的奶牛的时间。
输入格式
第 \(1\) 行: \(2\) 个用空格隔开的整数:\(N\) 和 \(M\) ;
第 \(2...N+1\) 行: 第 \(i+1\) 为 \(1\) 个整数: \(M_i\) ;
输出格式
第 \(1\) 行: 输出 \(1\) 个整数,为\(Farmer John\)把所有奶牛都载过河所需的最少时间;
样例
样例输入
5 10
3
4
6
100
1
样例输出
50
题目大意:
载船运牛,每载一头牛,运送时间越长,求最短的运送时间。
注意
\(①\) 注意回来的时间。
\(②\) \(M_i\) 指的是船上有 \(i\) 头牛时,增加 \(M_i\) 的时间,而不是第 \(i\) 头牛运的时候需要 \(M_i\) 的时间。
\(③\) 注意加上 \(m\) 本身。
思路
求数组的前缀和,使 \(M_i\) 的值代表船上有 \(i\) 头牛时,运送需要的时间。
决策:直接把这 \(i\) 头牛运过去;
或者先把 \(j\) 头牛运过去,回来在把剩下的 \(i-j\) 头牛运过去。
动态方程:\(dp[i]=min(dp[i],dp[j]+cow[i-j]+m)\)
代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=5000+50;
int n,m;
int Cow[maxn],dp[maxn];
int main(){
cin>>n>>m;
Cow[0]=m;//算上木筏的时间
for(int i=1;i<=n;i++){
cin>>Cow[i];
Cow[i]+=Cow[i-1];//求前缀和,便于计算
}
for(int i=1;i<=n;i++){
dp[i]=Cow[i];//初始化
for(int j=0;j<i;j++){
dp[i]=min(dp[i],dp[j]+Cow[i-j]+m);//决策
}
}
cout<<dp[n]<<endl;
return 0;
}