过河问题

贪心算法

过河问题

时间限制: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


#include <stdio.h>

void qsort(int num[], int l, int r)
{
    if (l < r)
    {
        int i = l, j = r, x = num[l];
        while (i < j)
        {
            while (i < j && num[j] >= x)
                j--;
            if (i < j)
                num[i++] = num[j];
            while (i < j && num[i] < x)
                i++;
            if (i < j)
                num [j--] = num[i];
        }
        num[i] = x;
        qsort(num, l, i-1);
        qsort(num , i+1, r);
    }
}

int main ()
{
    int i, j, t, n, num[1000];
    scanf("%d",&t);
    while (t--)
    {
        scanf("%d",&n);

        for (i = 0; i < n; i++)
            scanf("%d", &num[i]);

        qsort(num, 0, n-1);  // 快排

        int sum = 0;
        while (n >= 4)
        {
            if (num[1] + num[0] + num[n-1] + num[1] < num[n-1] +num[0]+num[0]+num[n-2] )
            {
                // 两个人同时接
                sum += num[1]; // 最快的和第二快的过河
                sum += num[0]; // 最快的回来送灯(剩下第二快的)
                sum += num[n-1]; // 最慢的和第二慢的过河
                sum += num[1];   // 第二块的回去送灯
                // 还有第二快的 和最快的没回来
            }
            else
            {
                // 一个人接
                sum += num[n-1];   // 最快的和最慢的过河
                sum += num[0];    //  最快的回去送灯
                sum += num[n-2];   // 最快的把 第二慢的接过去
                sum += num[0];  //  最快的回去  
                //还有第二快的和最快的没回来
            }
            n -= 2;   // 因为过去了两个人 还有两个人
        }
        if (n == 3)
        {
            sum +=  num[2] + num[0] + num[1];
        }
        if (n == 2)
        {
            sum += num[1];
        }
        if (n == 1)
        {
            sum += num[0];
        }

        printf("%d\n", sum);

    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值