题目地址:http://codeup.cn/problem.php?id=3296

3296: 过河问题

题目描述

在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过。如果各自单独过桥的话,N人所需要的时间已知;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,如何设计一个方案,让这N人尽快过桥。

输入

第一行是一个整数T(1<=T<=20)表示测试数据的组数
每组测试数据的第一行是一个整数N(1<=N<=1000)表示共有N个人要过河
每组测试数据的第二行是N个整数Si,表示此人过河所需要花时间。(0<Si<=100)

输出

输出所有人都过河需要用的最少时间

样例输入

1
4
1 2 5 10

样例输出

17

解题思路

对于一个人,直接过河

对于两个人,一起过河

对于三个人,最快的和任意一个一起过河,最快的回来,最快的和剩余一个一起过河

这里主要分析四个人过河的两种策略

策略一:最快的和任意一个一起过河,然后最快的再回来,再和任意的一个一起过河,然后最快的再回来

策略二:最快的和次快的一起过河,最快的回来,然后最慢的和次慢的一起过河,次快的回来,然后最快和次快的一起过河。

可以表示为 T1 T2 T3 T4(T1<T2<T3<T4),对应的过河顺序见下图

codeup3296 过河问题(贪心)

可以选用哪种策略取决于时间差t=T1+T3-2T2的大小,如果t<0,说明方法一用时少,如果t>0说明方法二用时少

对于多个人则每次过河的顺序取决于两个决策方法哪个用时比较少,以四个人为单位,按上述用时,比较哪个更小

例如对于6个人

方法一全部采用策略一

方法二既采用策略一也采用策略二

方法三全部采用策略二

每两个来回可以送过去两个人,选择哪一种策略重点min(a[0]*2+a[n-1]+a[n-2],a[0]+a[1]*2+a[n-1])

codeup3296 过河问题(贪心)

实现代码

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

int main(){
	int n,i,k,sum=0;
	int a[1010];
	cin>>k;
	while(k--){
		sum=0;
		cin>>n;
		for(i=0;i<n;i++) cin>>a[i];
		sort(a,a+n);
		while(n>3){
			sum+=min(a[0]*2+a[n-1]+a[n-2],a[0]+a[1]*2+a[n-1]);
			n-=2;
		}
		if(n==3) sum+=a[0]+a[1]+a[2];
		else if(n==2) sum+=a[1];
		else if(n==1) sum+=a[0];
		cout<<sum<<endl;
	}
	return 0;
} 

 

相关文章: