1032 迁徙过程中的河流 贪心 线性DP
作者:互联网
链接:https://ac.nowcoder.com/acm/contest/24213/1032
来源:牛客网
题目描述
牛市的幸存的先民在流星雨之后就忍痛离开了这片土地,选择迁徙,在迁徙的途中,他们需要渡过一条河。因为牛市的树木在流星雨中被严重破坏,所以他们只造出了一艘小船,船太小了,一次只能乘坐两人。牛市的先民们每个人划船的速度都不尽相同,所以每个人都有一个渡河时间T,为了保证船的平衡,当穿上有两个人的时候,需要他们按照慢的那个人的速度划船,也就是说船到达对岸的时间等于船上渡河时间长的那个人的时间。
现在已知N个人的渡河时间T,请问最少要花费多少时间,才能使所有人都过河。
输入描述:
输入文件第一行为先民的人数N(N≤100000)(N\leq 100000)(N≤100000),以下有N行,每行一个整数为每个人的渡河时间。
输出描述:
输出文件仅包含一个数,表示所有人都渡过河的最少渡河时间。示例1
输入
复制4 5 7 11 16
输出
复制42
说明
首先1,2先到河对岸花费7,然后1回来花费5,3,4到河对岸花费16,2回来花费7,1,2再到河对岸花费7
分析
随着人数变多,时间也会变多设f[i] 表示i 个人送到对岸的最小时间
有 N
个人需要渡河,有一条船,船上最多只能乘坐两人。第 i
个人一个人划船到对面需要 T[i-1]
时间。
为了保证船的平衡,当船上有两人时,需按照慢的那个人的速度划船,也就是说船到达对岸的时间等于船上渡河时间长的那个人的时间。
求所有人过河的花费时间最少为多少?
首先将 N
个人按照渡河时间从小到大排序,则第 1 个人和第 2 个人可以作为来回划船的人。
dp[i]
表示前 i+1
个人过河花费的最少的总时间。dp[0] = T[0]
,表示1 个人过河时间。dp[1] = T[1]
,两个人一起划到对岸。dp[i] = min(dp[i-1]+T[0]+T[i], dp[i-2]+T[0]+T[i]+T[1]+T[1])
。
前 i
个人渡河时间为 dp[i-1]
,还有 1 人需要渡河,由第 1 个人花费 T[0]
时间接第 i+1
个人,两人渡河时间为 T[i]
。
此时,dp[i] = dp[i-1] + T[0] + T[i]
。
前 i-1
个人渡河时间为 dp[i-2]
,还有两个人需要渡河,由第 1 个人花费 T[0]
时间划船回来,第 i
个人和第 i+1
个人一起过河花费时间为 T[i]
,再由第 2 个人将船划回来,时间为 T[1]
,和第 1 个人一起渡河,时间为 T[1]
。
此时,dp[i] = dp[i-2] + T[0] + T[i] + T[1] + T[1]
。
取两种方案的较小值。最后 dp[n-1]
是结果。
//-------------------------代码----------------------------
//#define int LL
const int N = 1e5+10;
int n,m;
int a[N],f[N];
void solve()
{
cin>>n;
fo(i,1,n) cin>>a[i];
sort(a+1,a+1+n);
f[1] = a[1];
f[2] = a[2];
for(int i = 3;i<=n;i++) {
f[i] = min(f[i-1] + a[1] + a[i],f[i-2] + a[1] + a[i] + 2 * a[2]);
}
// for(int i = 1;i<=n;i++) {
// cout<<f[i]<<' ';
// }
// cout<<endl;
cout<<f[n]<<endl;
}
signed main(){
clapping();TLE;
// int t;cin>>t;while(t -- )
solve();
// {solve(); }
return 0;
}
/*样例区
*/
//------------------------------------------------------------
标签:个人,int,花费,渡河,时间,DP,1032,dp,贪心 来源: https://www.cnblogs.com/er007/p/16468604.html