我(SDUTOJ_2868)

题目描述

n个人要过一座桥,只是在漆黑的夜里,没有火把显然是不行的。但是这n个人只有一个火把,并且这座桥每次最多只能通过两个人。
每个人的速度不同,若两人组队,队伍速度等于较慢一人的速度。你要做的是计算这n个人全部通过这座桥的最少时间。

输入

多组输入。每组数据的第一行是输入一个n,代表有n(1 <= n && n <= 500)个人,接下来的n个整数,代表着每个人穿过这座桥所需要的时间。

输出

输出一个整数,代表最优策略所需时间。

示例输入

4
1
10
5
2

示例输出

17

提示

假设人员编号按输入顺序从1到n,首先编号为1,4的人通过,编号为1的回来送火把,然后编号为2,3组队通过,编号为4的回来送火把,编号为1,4通过,结束。
Sum = 2 + 1 + 10 + 2 + 2 = 17。

代码

这题是一道你会了就很简单不会就很难办的一道贪心,当然,要把贪心的策略想清楚了,比赛的时候没想清楚就乱敲了一通,所以果断WA。

这题一共只有两种情况,一种就是可以先让花时间最少的两个人通过,然后让两人中花时间少的那个人回去送火把,再然后让还没过桥的花时间最多的两个人拿火把通过,再再然后已经过了桥的人中花时间最少的那个(就是一开始通过桥没回来的那个)再回来送火把= =还有一种就是让花时间最少的那个人来回送火把= =感觉有点绕= =假设有四个人要过桥,按照所花时间从小到大编号1,2,3,4。那么现在,我们可以先让1和2通过桥,然后1回来送火把,再让3和4通过桥,然后2回来送火把,然后1和2再通过,这是第一种方法,另一种方法就是,让1和2通过,1回来,1和3通过,1回来,1和4通过。当然我举的例子是两个数据量小又极端的例子,在真正过桥的时候往往是两种方法交替使用。。。下面上代码。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int main()
{
    int n;
    int a[555];
    while(scanf("%d", &n) != EOF)
    {
        for(int i = 0; i < n; i++)
            scanf("%d", &a[i]);
        sort(a, a + n);
        int ans = 0;
        if(n == 1)
        {
            printf("%d\n", a[0]);
            continue;
        }
        for(int i = n - 1; i > 1;)
        {
            if(2 * a[1] < a[0] + a[i - 1]) //这里是把两种方法所花时间的表达式化简了,自己算一下肯定能算出来这式子
            {
                ans += 2 * a[1] + a[0] + a[i];
                i -= 2;
            }
            else
            {
                ans += a[0] + a[i];
                i--;
            }
        }
        ans += a[1]; //观察上边的循环可以发现最后都是花时间最少的两个人还没通过,所以要加上最后他们两个通过的时间
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(我(SDUTOJ_2868))