Crossing River

Crossing River
Time Limit: 1000MS  Memory Limit: 10000K

Description

A group of N people wishes to go across a river with only one boat, which can at most carry two persons. Therefore some sort of shuttle arrangement must be arranged in order to row the boat back and forth so that all people may cross. Each person has a different rowing speed; the speed of a couple is determined by the speed of the slower one. Your job is to determine a strategy that minimizes the time for these people to get across.
 

Input

The first line of the input contains a single integer T (1 <= T <= 20), the number of test cases. Then T cases follow. The first line of each case contains N, and the second line contains N integers giving the time for each people to cross the river. Each case is preceded by a blank line. There won't be more than 1000 people and nobody takes more than 100 seconds to cross.
 

Output

For each test case, print a line containing the total number of seconds required for all the N people to cross the river.
 

Sample Input

1
4
1 2 5 10

 

Sample Output

17

 

Source

POJ1700

OpenJudge——百练1700

OpenJudge——NOI702

 

题解:

根据题意可以判断这道题用贪心。

做题时需要注意两点:

1.两人一起时速度由较慢的人速度决定。

2.船最多可承载两个人,划过去后必须有人划回来。

1 2 5 10 时间 合计
0 0 0 0 0 0
1 1 0 0 2 2
0 1 0 0 1 3
0 1 1 1 10 13
0 0 1 1 2 15
1 1 1 1 2 17

 

1 2 5 10 15 时间 合计
0 0 0 0 0 0 0
1 1 0 0 0 2 2
0 1 0 0 0 1 3
0 1 0 1 1 15 18
0 0 0 1 1 2 20
1 0 1 1 1 5 25
0 0 1 1 1 1 26
1 1 1 1 1 2 28

如果不用有人划回来,为了时间最短,最好时间相近的人两两组队,以1、2、5、10为例,可以1和2组队,5和10组队,这样时间可以每组中用时多的一个即可,其他任何组合方式都无法比这种用的时间短。如果人数为奇数个,则让前三个为组合。因此先将用时排序,由于数据量较小,任何排序方法都可以。

题目中要求船划过去后必须有人划回来,时间最短有两种可能(第一组除外,设该组中快的为A,慢的为B,所有人中最快的为C,第二快的为D):

可能1:

C和A过去,C回来。

C和B过去,C回来。

用时为2*t(C)+t(A)+t(B).

可能2:

C和D过去,C回来。

A和B过去,D回来。

用时为2*t(D)+t(C)+t(B).

如果t(C)+t(A)<2*t(D),则可能1时间短,否则可能2时间短。

将每一组最短时间加起来,最后不要忘记第一组的时间。

当组数为偶数时,最后最快的和第二快的一起过去,加上第二快的时间。

当组数为奇数时,第一组用可能1,但最后最快的不用回来,即加上第一快、第二快和第三快的时间。

<span style="font-size:18px;">#include<cstdio>
#include<cmath>
int a,b,c,d,e,f,g,i,m,n,j,x[10000]={0};
int main()
{
scanf("%d",&a);
for(n=1;n<=a;n++)
{
	scanf(" %d",&b);
	for(i=1;i<=b;i++)
	{
		scanf(" %d",&x[i]);
		for(m=1;m<i;m++)
		{
			if(x[i]<x[m])
			{
				c=x[i];
				x[i]=x[m];
				x[m]=c;
			}
		}
	}
	if(b%2==0)
	{
		c=x[2];
		for(i=4;i<=b;i=i+2)
		{
			if(x[i]+x[1]+x[2]*2<x[i-1]+x[i]+x[1]*2) c=c+x[i]+x[1]+x[2]*2;
			else c=c+x[i-1]+x[i]+x[1]*2;
		}
	}
	else
	{
		c=c+x[1]+x[2]+x[3];
		for(i=5;i<=b;i=i+2)
		{
			if(x[i]+x[1]+x[2]*2<x[i-1]+x[i]+x[1]*2) c=c+x[i]+x[1]+x[2]*2;
			else c=c+x[i-1]+x[i]+x[1]*2;
		}
	}
	printf("%d\n",c);
}
return 0;
}</span>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值