参考:http://www.clanfei.com/2013/05/1710.html
/*
过河问题
时间限制:1000 ms | 内存限制:65535 KB
难度:5
描述
在漆黑的夜里,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
参考:http://www.clanfei.com/2013/05/1710.html
先将数组S按过河时间从小到大排好序。
1.当N为1时,答案自然直接为S1
2.当N为2时,答案则是速度慢的一个,即S2
3.当N为3时,由速度最快的与其中一个先过河,速度快的回来,再与另一个过河,时间为S1 + S2 + S3
4.当N大于3时,问题开始变得复杂起来,我们需要寻找一个固定的规律,才能够将问题简单化,
由于过桥需要有人将手电筒带回原岸,返程的必定是速度叫快的一个,即速度快的可能往返多次,
因此由速度快的开始计算时间必然会非常复杂,而速度最慢的过河之后必定不会再回程,
因此我们从速度慢的先考虑,先将速度慢的送过河。但此时可能出现两种情况:
a.由于同时可以过两个人,因此可以考虑最快的与次快的过河,最快的回来,
最慢的与次慢的过河,次快回来,以此节省次慢的过河时间,
则最慢、次慢的过河时间为 S2 + S1 + Sn + S2
b.而另一种最容易考虑到的自然是最快的送最慢的过河,然后最快的回来,
此时次慢变为最慢,再让最快的送其过河,最快再回来……
那么最慢、次慢的过河时间为 Sn + S1 + Sn-1 + S1
即简化为送最慢的两个人先过河,在这两种情况中取花费时间最少的方式,规模缩小为n - 2的同一问题
*/
#include <iostream>
using namespace std;
inline void mySweap(int&a,int&b)
{
int temp=a;
a=b;
b=temp;
}
int getPos(int* p,int posBeg,int posEnd)
{
int key=p[posEnd];
int i=posBeg,j=posEnd-1;
while ( j>=i ){
while ( j>=i && p[j]>=key){
--j;
}
while ( p[i]<key ){
++i;
}
if ( i<j ){
mySweap(p[i--],p[j--]);
}
}
mySweap(p[i],p[posEnd]);
return i;
}
//从小到大
void quickRank(int* p,int beg,int end)
{
if ( beg<end ){
int pos=getPos(p,beg,end);
quickRank(p,beg,pos-1);
quickRank(p,pos+1,end);
}
}
void sulotion(const int *p,const int nSize)
{
int leftPerson=nSize-1;
int totalTime=0;
while ( leftPerson>=3 ){
totalTime+=(p[0]+2*p[1]+p[leftPerson])<(2*p[0]+p[leftPerson-1]+p[leftPerson])
? (p[0]+2*p[1]+p[leftPerson]):(2*p[0]+p[leftPerson-1]+p[leftPerson]);
leftPerson-=2;
}
if ( leftPerson==2 ){
totalTime+=p[0]+p[1]+p[2];
}
if ( leftPerson==1 ){
totalTime+=p[1];
}
if ( leftPerson==0 ){
totalTime+=p[0];
}
cout<<totalTime<<endl;
}
int main()
{
int a[1010];
int num;
cin>>num;
while ( num-- ){
int personNum;
cin>>personNum;
for ( int i=0 ; i<personNum ; ++i ){
cin>>a[i];
}
quickRank(a,0,personNum-1);
sulotion(a,personNum);
}
/*for ( int i=0 ; i<2 ; ++i ){
cout<<a[i]<<" ";
if ( (i+1)%5==0 ){
cout<<endl;
}
}*/
return 0;
}