题意:一个船能乘2人,船的运行速度为2人中较慢一人的速度,问把n个人运到对岸,最少需要多久。
分析:我们设最快的为a,次快的为b,最慢的为z,次慢的为y。
我们先考虑如何将y,z运到对岸,可以ab,a,yz,b(yz一起运),也可以ay,a,az,a(yz分开运)。
我们这两种情况都是只考虑y,z,没考虑x的,那如果y需要和x一起运怎么办呢(x是第三慢的人)
一起运yz时间:b+a+z+b,分开运时间:y+a+z+a
比较二者大小只需比较2*b和y+a的大小。
我们假设单运较快则2*b>y+a,
y>x => y+a>x+a => 2*b>y+a>x+a => 2*b>x+a
通过不等式可以证明如果单运y,z比一起运快,那么yx一起运绝对比单运y,x慢,所以y和x不可能一起运。
那么有没有可能z需要和x一起呢,也是不可能的。
运送z不可能影响此4人之外的人。
一起运,相当于让某人借助z的速度慢得特点,来使得其本身的速度不表现出来(我们注意到一起运的时间时我们并没有用到y的速度。)
也就相当于z屏蔽了一个人的运行时间,所以一定会选择一个最大的屏蔽,而不会选择较小的。否则那个大的就会被遗留下来,给以后的运送增加负担。
这样每次运最后两个可以一直让总数减少直到3个以内,直接处理即可
View Code
#include#include #include #include #include using namespace std; #define maxn 1006 int n, f[maxn]; int cal(int a, int b, int y, int z) { return min(z + a + y + a, b + a + z + b); } void work() { int i = n - 1; int ans = 0; while (i > 2) { ans += cal(f[0], f[1], f[i - 1], f[i]); i -= 2; } if (i == 2) ans += f[0] + f[1] + f[2]; else ans += f[1]; printf("%d\n", ans); } int main() { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &f[i]); sort(f, f + n); if (n == 1) { printf("%d\n", f[0]); return 0; } work(); return 0; }