题目链接:https://vjudge.net/problem/POJ-3404

题意:n个极限速度不同的人要过桥,一开始所有人在桥的一边,每次最多两个人同时过桥,过桥时需要用一把火炬并且全场只有一把火炬,问所有人到达桥的另外一边所需最短时间。

思路:凭直觉很多人都会立刻想到每次都让最快的人在桥两边来回陪同其他人过桥,但是当遇到类似于1  2    10  11,这种,最优解为   1 2,1,10 11,2,1 2,并不是1 2,1,1 10,1,1 11.

  设a最快,b次快,d次慢,c最慢,每次有两种策略可供选择(剩余人数大于等于4,其他情况很容易计算):

    1.a  b,a,c  d,b,

    2.a  d,a,a  c,a.

  每次对两种方案进行比较即可。

代码如下:

 1 #include<cstdio>
 2 #include<list>
 3 #include<iostream>
 4 #include<algorithm>
 5 using namespace std;
 6 int main(){
 7     list<int> lt;
 8     int n,val[60];
 9     scanf("%d",&n);
10     for(int i=1;i<=n;i++){
11         scanf("%d",&val[i]);
12     }
13     sort(val+1,val+1+n);
14     for(int i=1;i<=n;i++)
15         lt.push_back(val[i]);
16     list<int>::iterator it;
17     int ans=0;
18     while(lt.size()>0){
19         if(lt.size()>=4){
20             int a=*lt.begin(),b,c,d;
21             it=lt.begin();it++;
22             b=*it;
23             it=lt.end();
24             it--;d=*it;
25             it--;c=*it;
26             int t1=b+a+d+b,t2=d+a+c+a;
27             ans+=min(t1,t2);
28             it=lt.end();
29             it--;lt.erase(it);
30             it=lt.end();it--;lt.erase(it);
31         }
32         else if(lt.size()==3){
33             int a,b,c;
34             it=lt.begin();
35             a=*it;it++;
36             b=*it;it++;
37             c=*it;
38             int t=b+a+c;
39             ans+=t;
40             break;
41         }
42         else if(lt.size()==2){
43             it=lt.begin();it++;
44             ans+=*it;break;
45         }
46         else {
47             ans+=*lt.begin();
48             break;
49         }
50     }
51     printf("%d",ans);
52     return 0;
53 }
01-26 09:35