其他分享
首页 > 其他分享> > 1032 迁徙过程中的河流 贪心 线性DP

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