acm_47 过河问题

来源:互联网 发布:星星知多少 编辑:程序博客网 时间:2024/06/06 21:41

过河问题

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

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

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

简化模型到最后  每次应该是2个人过去 一个人回来  所以每次河对岸应该是最后增加一个人

然后对于每次过河回来的人应该是河对岸的过河速度最快的人

很自然的想到 每次都把最快的人带去 那么让最快的人回来 那么回来的时间最短

但是当n=4的时候 我们可以发现 可能出现问题,就是 我们让最快和次快的人先过河 然后让最快的回来,之后再让2个最慢的人过去,次快的人回来,2个最快的人过去,这样 满足 timer[0]+timer[2]>2*timer[1]的时候之前的结论推翻了,现在我们就该认识的这种情况下我们应该分情况讨论

接下来我们要确认是否还有特殊情况,先思考当有n个人过河,  那么timer[n-1] 这个过河时间 肯定是省不了的,那么我们就应该考虑让船的返回时间最短,现在考虑 n>4的情况, 这样按照上一段的讨论,最慢和次慢的人应该一起分析,最后获取到的时间分别对应着将最慢和次慢的人送到对岸的时间,时间不可缩短,所以最后就可以得出下列程序

import java.util.Arrays;
import java.util.Scanner;

//acm_47
public class PassRiver {

    publicstatic void main(String[] args) {
         PassRiver passRiver = new PassRiver();
         passRiver.solution();
    }

    public voidsolution() {
       in = newScanner(System.in);
       int groups =in.nextInt();
       for (int i =0; i < groups; i++) {
         getDate();
         System.out.println(handle(num));
       }
    }
    Scannerin;
    intnum;
   int[]  timer;
    private voidgetDate(){
       num =in.nextInt();
       timer = newint[num];
      
       for(int i =0 ; i < timer.length;i++){
          timer[i] =in.nextInt();
       }
      
      Arrays.sort(timer);
    }
   //这里的逻辑是对数据进行处理,准备采用递归的方法,穿进去的是剩余的人数
    private inthandle(int index){
      switch(index){
      case 1:
         return timer[0];
      case 2:
         return timer[1];
      case 3:
         returntimer[0]+timer[1]+timer[2];
      }
      return Math.min(timer[0]+timer[index-2],2*timer[1])+timer[index-1]+timer[0] + handle(index-2);
    }
}

0 0
原创粉丝点击