【题解】Crossing River

题目描述

  几个人过河,每次过两人一人回,速度由慢者决定,问过河所需最短时间。

 

输入格式

  输入t组数据,每组数据第1行输入n,第2行输入n个数,表示每个人过河的时间。

 

输出格式

  输出t行数据,每行1个数,表示每组过河最少时间。

 

输入样例

1

4

1 2 5 10

 

 

输出样例

17

 

题解

   容易想到,我们要尽可能利用速度快的人,且尽可能先把慢的人送走。

  据此可以想到贪心策略:设$n$个人的时间升序排列为$a_{1}$到$a_{n}$,那么我们就让第$n$个人把第$1$个人运到对岸,再让第$1$个人自己回来,然后$n = n - 1$,继续上述过程。

  但是当我们运了第$(n - 1)$和第$n$个人时,时间为$a_{1} + a_{1} + a_{n - 1} + a_{n}$,此时还有一种策略,即先让第$2$个人运第$1$个人过去,第$1$个人回来,再让第$n$个人运第$(n-1)$个人过去,然后第$2$个人回来,这样总时间就为$a_{1} + a_{2} + a_{2} + a_{n}$。

  当$a_{1} + a_{n - 1} > a_{2} + a_{2}$时,实际第二种方案好过第一种方案,每次去最优方案即可。

【题解】Crossing River
#include <iostream>
#include <algorithm>

#define MAX_N (100 + 5)

using namespace std;

int T;
int n;
int a[MAX_N];
int ans;

int main()
{
    cin >> T;
    while(T--)
    {
        ans = 0;
        cin >> n;
        for(register int i = 1; i <= n; ++i)
        {
            cin >> a[i];
        }
        sort(a + 1, a + n + 1);
        while(n >= 4)
        {
            ans += min(a[1] + a[1] + a[n - 1] + a[n], a[1] + a[2] + a[2] + a[n]);
            n -= 2;
        }
        if(n <= 2) ans += a[n];
        else ans += a[1] + a[2] + a[3];
        cout << ans << "\n";
    }
    return 0;
参考程序

 

上一篇:River Hopscotch


下一篇:关于C++中constexpr的用法