POJ 3404 Bridge over a rough river 贪心,每次算最大的两个人去对岸的最少用时

Bridge over a rough river
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 4033 Accepted: 1649

Description

A group of N travelers (1 ≤ N ≤ 50) has approached an old and shabby bridge and wishes to cross the river as soon as possible. However, there can be no more than two persons on the bridge at a time. Besides it's necessary to light the way with a torch for safe crossing but the group has only one torch.

Each traveler needs ti seconds to cross the river on the bridge; i=1, ... , N (ti are integers from 1 to 100). If two travelers are crossing together their crossing time is the time of the slowest traveler.

The task is to determine minimal crossing time for the whole group.

Input

The input consists of two lines: the first line contains the value of N and the second one contains the values of ti (separated by one or several spaces).

Output

The output contains one line with the result.

Sample Input

4
6 7 6 5

Sample Output

29



题目的意思是有一座桥,开始有n个旅行者在桥左边.问怎么才能最快全体通过这个桥.

要求是,这桥每次最多过两个人,所需要的时间取决于比较慢的那个人,而且过去的时候要带上火棒来照明,火棒只有一个,所以除了最后一次过去的人,之前都要有人把火棒给拿回来给后面的人用.

输入的n代表人数, ti 代表每个人过桥的用时.

再人数比较多的时候 ,这里有两种可能,

接下来讲解下第一种可能

A代表 速度最快的人 ti最小

B代表 速度第二快的人

Y代表 速度第二慢的人

Z代表 速度最慢的人  ti最大


如果ABYZ数值差距不是很大的时候, 比如案例的7665

那么 每次都是A 带一个人过去,然后A回来.

所用时间 是A*2+B+Y+Z ,因为带最后一个人过去后不用再回来了


当人数大于等于4的时候

人多的时候, 我是每次算最大的两个人过去的用时 .  用时等于Y +Z+2*A,  最后A要把火炬拿回来,给接下来的两个人用


第二种可能是

AB与YZ如果差距很大的话.

可以先让AB 一起过去 花费B时间

再让A 把火炬拿回来 花费A时间

再让YZ一起过去, 花费D时间

再让B把火炬拿回来 花费B时间


这样 AB两个小的就回到了左边, YZ两个大的成功去了左边 总用时是A+D+2*B


总的来说,就是每次过去两个最大的 用时是 Y +Z+2*A,  和A+D+2*B 中小的那个


#include<stdio.h>
#include<algorithm>
using namespace std;
int min(int a,int b)
{
	return a<b?a:b;
}

int main()
{
	int sum,i,j;
	int n,a[200];
	scanf("%d",&n);
	for(i=0;i<n;i++)
	{
		scanf("%d",&a[i]);
	}
	sort(a,a+n);
	if(n<=2)//特殊情况
	{
		if(n==1)
		printf("%d\n",a[0]);
		if(n==2)
			printf("%d\n",a[1]);
		return 0;
	}
	sum=0;
	for(i=n-2;i>=2;i-=2)//每次过去最大的  所以从n-2 这边开始
	{
		sum+=min(a[i]+a[i+1]+2*a[0],a[i+1]+a[0]+a[1]*2);
	}
	for(j=1;j<=i+1;j++)
	{
		sum+=a[j];
	}
	if(i>0)
	sum+=i*a[0];
	printf("%d\n",sum);
	return 0;
}








  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值