NYoj47 过河问题

来源:互联网 发布:日剧知乎 编辑:程序博客网 时间:2024/05/18 22:50

过河问题

时间限制:1000 ms  |  内存限制:65535 KB
难度:5
描述

在漆黑的夜里,N位旅行者来到了一座狭窄而且没有护栏的桥边。如果不借助手电筒的话,大家是无论如何也不敢过桥去的。不幸的是,N个人一共只带了一只手电筒,而桥窄得只够让两个人同时过。如果各自单独过桥的话,N人所需要的时间已知;而如果两人同时过桥,所需要的时间就是走得比较慢的那个人单独行动时所需的时间。问题是,如何设计一个方案,让这N人尽快过桥。 

输入
第一行是一个整数T(1<=T<=20)表示测试数据的组数
每组测试数据的第一行是一个整数N(1<=N<=1000)表示共有N个人要过河
每组测试数据的第二行是N个整数Si,表示此人过河所需要花时间。(0<Si<=100)
输出
输出所有人都过河需要用的最少时间
样例输入
141 2 5 10
样例输出
17


解题思路:贪心...
1.排序
2.这个过桥是需要有人不断的送送手电筒,最终才能全过。
送手电筒当然是最快的那个人不断的来回才能达到时间最短。
情况有俩种:
当然首先肯定是a0与a1一起过去,然后开始送手电筒

(1) a0不断的来回跑,即 a0(送手电筒) + a(i)(带a0一起走) + a0(送手电筒) + a(i-1)(带a0一起走);....

(2) 当a1 与 a0 速度差不多时,a0与a1交替送手电筒,即 a0(送手电筒) + a(i)(带a(i-1)一起走) + a1(送手电筒) + a1(回来接a0走)...

每次俩种情况取最小累加。最终即为最短。

当然这里还需要考虑 n 为 奇数 的情况。

因为当人数为奇数时,肯定最后有一个人单走,所以在末尾判断后  将 a0(送手电筒) + a2(倒的来只留下了它) 即可


#include <stdio.h>#include <stdlib.h>int cmp(const void *a,const void *b){    return *(int*)a - *(int*)b;}int main(){    int i,t,n,a[1001];    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(i=0;i<n;i++)           scanf("%d",&a[i]);        qsort(a,n,sizeof(a[0]),cmp);        int sum = a[1];//第一次肯定是a0和a1一起走,所以记为a1时间        if(n <= 2)//当人数<=2时取最大时间即可            sum = a[n-1];        int sum1,sum2;        for(i=n-1;i>2;i -= 2)        {            sum1 = a[0] + a[i] + a[1] + a[1];//a0返回,ai和ai-1走,即为ai时间,然后a1返回,然后a1与a0走,即为a1时间            sum2 = a[0] + a[i] + a[0] + a[i-1];//每次都是a0接人            sum += (sum1 < sum2)?sum1:sum2;//取最短时间累计,这里关键,错了好多回        }        if(n%2 && n!=1)//如果人数为奇数,肯定回有一个人单走,即为a2,a0是往回送电筒的           sum += a[0] + a[2];        printf("%d\n",sum);    }    return 0;}



0 0