经典划船渡河问题

  经典的一帮人,一艘船,渡河问题:
  n 个人,一艘船,每次过河穿上最多坐两个人,每个人有一个过河时间 a[i],两个人一起坐船,时间为慢的人的时间,过去之后,需要有人带着船回来,才能继续过河,这个时间也需要计算,问最短需要多少时间能够所有人过河(最后一次船不需要回来)?

样例输入:
5
1 2 4 5 15
样例输出:
27

  首先能明确的是,如果过河能够两个人一起过,那就两个人一起过,因为一个人过的话太耽误时间了;回来一定是一个人回来,这个很明显。然后进行讨论:

1个人的情况

  我们首先考虑一个人的情况,很简单,就是自己一个人坐船过河就行,也就是 a[0]。

2个人的情况

  两个人也很简单,两个一起过河,时间是慢的人的时间,也就是如果是升序数组,就是 a[1]。

3个人的情况

  A、B、C 三个人的话,排序变成耗时 A <= B <= C,也就是 A 是最快的,那么最快过河的方案一定是 A 和 (B or C)一起过,然后 A 回来,再陪另一个人过,这样时间就是 A + B + C,也就是 a[0] + a[1] + a[2]。

n个人的情况(n > 3)

  大于三个人的话,我们按 A、B、C、D 四个人讨论(其中 A <= B <= C <= D),每次将最慢得到两个人送过河,有两种情况:
1、最快的人送最慢的两个人过河

A 和 D 过河,耗时 D;
A 回来,耗时 A;
A 和 C 过河,耗时 C;
A 回来,耗时 A。

  四步后总人数就减少 2,耗时 2 * A + C + D。这种方案其实就是 A、C、D 三个人过河的情况,不过最后船要回来。
2、最快的两个人送最慢的两个人过河

A 和 B 过河,耗时 B;
A 回来,耗时 A;
C 和 D 过河,耗时 D;
B 回来,耗时B。

  这四步后总人数同样减小 2,耗时 A + 2 * B + D

  上边为什么说是最慢,因为总人数 > 4 的时候是一次一次按四个人算的,每次送过去最慢的两个人,相当于每次送 a[n] 和 a[n - 1],然后 n -= 2。上边两种方案其实看得就是 A + C2 * B 的大小,不过代码不需要比较,代码如下:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
	int n, sum = 0;
	cin >> n;
	vector<int> a(n);
	for (int& i : a) cin >> i;
	sort(a.begin(), a.end());
	while (n > 3) {
		sum += min(2 * a[1] + a[0] + a[n - 1],
			       a[n - 1] + 2 * a[0] + a[n - 2]);
		n -= 2;
	}
	if (n == 3)      sum += a[0] + a[1] + a[2];
	else if (n == 2) sum += a[1];
	else             sum += a[0];
	cout << sum  << endl;
}
  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值