poj3404

题意:一个船能乘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 <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
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;
}

posted @ 2011-10-10 18:50  金海峰  阅读(326)  评论(0编辑  收藏  举报