ICPC North America Qualifier Contest 2015 G Safe Passage 【最快过桥问题】

Description

A group of friends snuck away from their school campus, but now they must return from the main campus gate to their dorm while remaining undetected by the many teachers who patrol the campus. Fortunately, they have an invisibility cloak, but it is only large enough to cover two people at a time. They will take turns as individuals or pairs traveling across campus under the cloak (and by necessity, returning the cloak to the gate if others remain). Each student has a maximum pace at which he or she is able to travel, yet if a pair of students are walking under the cloak together, they will have to travel at the pace of the slower of the two. Their goal is to have everyone back at the dorm as quickly as possible.

As an example, assume that there are four people in the group, with person A able to make the trip in 1 minute, person B able to travel in 2 minutes, person C able to travel in 7 minutes, and person D able to travel in 10 minutes. It is possible to get everyone to the dorm in 17 minutes.

Input

The input is a single line beginning with an integer, 2≤N≤15. Following that are N positive integers that respectively represent the minimum time in which each person is able to cross the campus if alone; these times are measured in minutes, with each being at most 5000. (It is a very large campus!) 

Output

Output the minimum possible time it takes to get the entire group from the gate to the dorm. 

样例输入1 

2 15 5

样例输出1

15

样例输入2

4 1 2 7 10

样例输出2

17

样例输入3

5 12 1 3 8 6

样例输出3

29

题目大意:

N个人过桥,每个人过桥需要的时间为ti(1<=i<=N).每次最多两个人过桥,并且还要回来一个,求最快过桥时间。 

分析:

经典的最快过桥问题。

最佳方案构造:  

1) 如果N=1、2,所有人直接过桥。  

2) 如果N=3,由最快的人往返一次把其他两人送过河。  

3) 如果N≥4,设A、B为走得最快和次快的旅行者,过桥所需时间分别为a、b;而Z、Y为走得最慢和次慢的旅行者,过桥所需时间分别为z、y。那么    

当2b>=a+y时,使用模式一将Z和Y移动过桥;   

当2b<a+y时,使用模式二将Z和Y移动过桥;    

这样就使问题转变为N-2个旅行者的情形,从而递归解决之。

其中

模式一:用a把z送过去,a回来。再用a把y送过去,a再回来。(time1=z+a+y+a)

模式二:a,b先过去,a回来。y,z过去,b回来。(time2=b+a+z+b)

具体解释见代码。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <queue>
#define INF 0x3f3f3f3f
#define mst(a,num) memset(a,num,sizeof a)
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define repd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
typedef vector<int> VI;
const ll mod = 1e9 + 7;
const int maxn = 5000 + 5;

int a[maxn];
int ans=0;

void dfs(int l,int r){
    if(l==r){                       //剩一个人没过去
        ans+=a[l];
        return;
    }
    if(r-l==1){                     //剩两个人没过去
        ans+=max(a[l],a[r]);
        return;
    }
    if(r-l==2){                     //剩三个人没过去
        ans+=a[r]+a[l]+a[r-1];
        return;
    }
    if(2*a[l+1]>=a[l]+a[r-1]){      //分情况递归求解
        ans+=a[r]+a[l]+a[r-1]+a[l];
        dfs(l,r-2);
    }
    else{
        ans+=a[l+1]+a[l]+a[r]+a[l+1];
        dfs(l,r-2);
    }
}

int main() {
    int n;
    scanf("%d",&n);
    rep(i,1,n){
        scanf("%d",a+i);
    }
    sort(a+1,a+n+1);                //先排序保证最快的是前两个
    dfs(1,n);
    printf("%d\n",ans);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值