NC207781 迁徙过程中的河流

题目链接

题目

题目描述

牛市的幸存的先民在流星雨之后就忍痛离开了这片土地,选择迁徙,在迁徙的途中,他们需要渡过一条河。因为牛市的树木在流星雨中被严重破坏,所以他们只造出了一艘小船,船太小了,一次只能乘坐两人。
牛市的先民们每个人划船的速度都不尽相同,所以每个人都有一个渡河时间T,为了保证船的平衡,当穿上有两个人的时候,需要他们按照慢的那个人的速度划船,也就是说船到达对岸的时间等于船上渡河时间长的那个人的时间。
现在已知N个人的渡河时间T,请问最少要花费多少时间,才能使所有人都过河。

输入描述

输入文件第一行为先民的人数 N (N100000) ,以下有N行,每行一个整数为每个人的渡河时间。

输出描述

输出文件仅包含一个数,表示所有人都渡过河的最少渡河时间。

示例1

输入

4
5
7
11
16

输出

42

说明

首先1,2先到河对岸花费7,然后1回来花费5,3,4到河对岸花费16,2回来花费7,1,2再到河对岸花费7

题解

知识点:线性dp,贪心。

给出一个贪心结论,因为时间短的和时间长的一起无法发挥时间短的收益,因此要么用时间最短的人作为运输媒介来回跑(这因为最短的人作媒介一定使得来回运输一个人的成本最低),要么两个时长相近的人一起。显然,先从小到大排序,方便处理。

dp[i] 表示运到第 i 个人的最短时间。先让最短时间的两人过去作为运输媒介,dp[1]=t[1],dp[2]=t[2] 。第一种方法:先用 t[1]1 号回去,用 t[i]i 号过去,共 t[1]+t[i] ;第二种方法:先用 t[1]1 回去,再用 t[i]i1i 过去,再用 t[2]2 回去,用 t[2]12 过去,共 t[1]+t[i]+2t[2] 。于是有转移方程:

dp[i]=min(dp[i1]+t[1]+t[i],dp[i2]+t[1]+t[i]+2t[2])

时间复杂度 O(nlogn)

空间复杂度 O(n)

代码

#include <bits/stdc++.h>
using namespace std;
int t[100007], dp[100007];///表示运了i个人
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n;
cin >> n;
for (int i = 1;i <= n;i++) cin >> t[i];
sort(t + 1, t + n + 1);///从小到大运人
dp[1] = t[1];
dp[2] = t[2];
for (int i = 3;i <= n;i++) dp[i] = min(dp[i - 1] + t[1] + t[i], dp[i - 2] + t[1] + t[i] + 2 * t[2]);
///先让最小的两人过去,用这两个人运。因为能坐两个人,所以可以考虑两种情况
///1回来接i过去;1回来i-1和i过去,2回来接1回去
cout << dp[n] << '\n';
return 0;
}
posted @   空白菌  阅读(39)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
点击右上角即可分享
微信分享提示