过河问题

来源:互联网 发布:js调用微信内置浏览器 编辑:程序博客网 时间:2024/06/07 02:29

过河问题

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

 这道题目呢 我们应该整理好思路 先从易到难 推出最终的规律 

  首先呢 我们从一个人开始 直接过去就好 那么最短时间一定是这个人过桥需要的时间

  然后 两个人 也是直接过去就好 最短时间应该是 相对来说过河时间较长的那个人 

  三个人 不难想出 方法是 过桥需要时间最短的那个人 带时间较长的那个人先过河 然后回来 带领一个人再过去 那两个人没有绝对的顺序 因为不管带哪一个时间都相同 都是最短时间 

  然后是四个人  这个就需要一些想法了 好多人一开始的想法跟三个人过桥相同 都是用时最短的那个人依次带剩下的人过桥 但是好好想想 这是一道难度为五的题 应该不会这么简单的让你想到解决办法  所以你就应该好好思考了

  方法是这样的 首先 用时最短的两个人先过去  然后 用时最短的那个 回来 再让用时较长的两个人过桥 让用时最短的两个人中的另一个人回去 最后那两个人一起过来就行了 这就是四个人的 用时最短的另一种方法  然后判断一下 两种方法所用的时间 选取出短的一种

  再分析五个人  同样的 也是用时最短的两个人 先过桥 其中一个人回来  让用时最长的那两个人过去 之前过去的另一个人再回来 然后发现桥这边就只剩下三个人和一般的用时最短的那个人带时间较长的那些人过桥比较  然后就跟前面的三个人分析的一样啦

  到这里基本就可以找到规律了  人数是双数的话 就以用时最短的两个人为介质 把用时最长的两个人转移到河对面 依次转移就行了 最后会剩下 用时最短的那两个人  过去就行了 

 人数是单数的话 也是两个两个转移 只是到了最后 这边还有三个人 就可以是 用时最短的人 带其他两个人 依次过河


这是AC代码   仅供参考

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int comp(const void*a,const void*b);
int main()
{
int N;
scanf("%d",&N);
while(N--)
{
int i,n;
int k=0,num=0;
int a[1002];
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
k++;
}
qsort(a,n,sizeof(a[0]),comp);
if(k==2)
{
num=a[1];
}
else if(k==1)
{
num=a[0];
}
else while(1)
{
int num1=0,num2=0;
k=k-2;
if(k==1)
{
num=num+a[2]+a[1]+a[0];
break;
}
if(k==0)
{
num=num+a[1];
break;
}
num1=num1+a[0]+2*a[1]+a[k+1];
num2=num2+2*a[0]+a[k+1]+a[k];
if(num1>num2)
num=num+num2;
else 
num=num+num1;
}
printf("%d\n",num);
}
return 0;
}




int comp(const void*a,const void*b)
{
return *(int*)a-*(int*)b;
}

0 0
原创粉丝点击