过河问题的代码实现

来源:互联网 发布:全国地图软件下载 编辑:程序博客网 时间:2024/05/09 19:36
问题描述

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

问题分析

这个问题的解决方案,充分体现了能者多劳(用时短的人必须多跑几次以便传递手电筒),也就是需要用到贪心算法。要么是最快的带最慢的,然后回来带第二慢的,依次带完,要么是最快的两个先过去,然后最快的把手电筒送回来,让最慢的两个过去,然后让第二快的把手电筒送过来。即将过河的人按其过河时间长短从大到小排序,设为对于时间排序得到S(1) <= S(2) .... S(n-1) <= S(n)
先考虑N=1时:
一个人过河时间肯定是S(1)
N = 2时:
时间为 S(2)
N = 3时:
时间则为 S(1)+S(2)+S(3)
N ≥ 4 时:
则有两种情况:
1.第一短的带最长的,再回来带第二短的,依次带完
时间为:(N-2)S(1)+S(2)+······S(n);
2.第一短带第二短,第一短回来,把手电给最长和第二长,再让第二短回来,依次类推

实现需求
(1)确定程序框架
由分析可知,首先把每个人的过河时间存储到数组中再排序,然后通过集合让人和时间一一对应起来,然后统计过桥时间及输出详细的过桥步骤,最后输出总时间。程序框架如以下代码所示:
package com.game_01;import java.util.Arrays;import java.util.Scanner;import java.util.HashMap;public class CrossBridge {static HashMap<Integer, String> hm = new HashMap<>();static Scanner sc = new Scanner(System.in);static int n = Integer.parseInt(sc.nextLine());static int[] time = new int[n];public static void main(String[] args) { //确定过河的人数 int sum =0; int a; System.out.println("过河的人数为" +n);  //将人和速度一一对应起来for (int i = 0; i < n; i++) {System.out.println("请输入第"+(i+1)+"个人的过河速度");time[i] = Integer.parseInt(sc.nextLine());System.out.println("请输入第"+(i+1)+"个人的姓名");String name = sc.nextLine();hm.put(time[i], name);}//将过桥时间排序Arrays.sort(time);//人数大于等于四人时进行如下循环for (a = n-1; a > 2; a-=2) {//最快的两个送最慢的两个过去if ((time[0] + time[1] + time[1] + time[a]) < (time[0] + time[0] + time[a-1] + time[a])) {sum = sum + time[0] + time[1] + time[1] + time[a];step2(0,1,a-1,a);//输出详细过程}else {//最快的送最慢的两个过去sum = sum + time[0] + time[0] + time[a-1] + time[a];step1(0,1,a-1,a);//输出详细过程}}//人数为三个人时if (a == 2) {sum = sum + time[0] + time[1] + time[2];step3(0,1,a);}else if (a == 1) {//人数为两人时sum = sum + time[a];step4(a);}else {sum = sum + time[0];}System.out.println("最短过桥时间为" +sum);}


(2)完成程序
在原有框架上进行补充就可得到完整的程序
import java.util.Arrays;import java.util.Scanner;import java.util.HashMap;public class CrossBridge {static HashMap<Integer, String> hm = new HashMap<>();static Scanner sc = new Scanner(System.in);static int n = Integer.parseInt(sc.nextLine());static int[] time = new int[n];public static void main(String[] args) { //确定过河的人数 int sum =0; int a; System.out.println("过河的人数为" +n);  //将人和速度一一对应起来for (int i = 0; i < n; i++) {System.out.println("请输入第"+(i+1)+"个人的过河速度");time[i] = Integer.parseInt(sc.nextLine());System.out.println("请输入第"+(i+1)+"个人的姓名");String name = sc.nextLine();hm.put(time[i], name);}//将过桥时间排序Arrays.sort(time);//人数大于等于四人时进行如下循环for (a = n-1; a > 2; a-=2) {//最快的两个送最慢的两个过去if ((time[0] + time[1] + time[1] + time[a]) < (time[0] + time[0] + time[a-1] + time[a])) {sum = sum + time[0] + time[1] + time[1] + time[a];step2(0,1,a-1,a);//输出详细过程}else {//最快的送最慢的两个过去sum = sum + time[0] + time[0] + time[a-1] + time[a];step1(0,1,a-1,a);//输出详细过程}}//人数为三个人时if (a == 2) {sum = sum + time[0] + time[1] + time[2];step3(0,1,a);}else if (a == 1) {//人数为两人时sum = sum + time[a];step4(a);}else {sum = sum + time[0];}System.out.println("最短过桥时间为" +sum);}//方法一:最快的将最慢的两个送过去private static void step1(int a, int b, int y, int z) {//获取人名String pA = hm.get(time[a]);String pY = hm.get(time[y]);String pZ = hm.get(time[z]);//获取时间int tA = time[a];int tY = time[y];int tZ = time[z];System.out.println(pA + "和" + pZ + "过桥,花费" + tZ + "分钟");System.out.println(pA + "回来,花费" + tA + "分钟");System.out.println(pA + "和" + pY + "过桥,花费" + tY + "分钟");System.out.println(pA + "回来,花费" + tA + "分钟");}//方法二:最快的两个将最慢的两个送过桥private static void step2(int a, int b, int y, int z) {//获取人名String pA = hm.get(time[a]);String pB = hm.get(time[b]);String pY = hm.get(time[y]);String pZ = hm.get(time[z]);//获取时间int tA = time[a];int tB = time[b];int tZ = time[z];System.out.println(pA + "和" + pB + "过桥,花费" + tB + "分钟");System.out.println(pA + "回来,花费" + tA + "分钟");System.out.println(pY + "和" + pZ + "过桥,花费" + tZ + "分钟");System.out.println(pB + "回来,花费" + tB + "分钟");}//方法三:有三个人过桥的时候private static void step3(int a, int b, int c) {System.out.println(hm.get(time[a]) + "和" + hm.get(time[b]) + "过桥,花费" + time[b] + "分钟");System.out.println(hm.get(time[a]) + "回来,花费" + time[a] + "分钟");System.out.println(hm.get(time[a]) + "和" + hm.get(time[c]) + "过桥,花费" + time[c] + "分钟");}//方法四:有两个人过桥private static void step4(int a) {System.out.println(hm.get(time[0]) + "和" + hm.get(time[a]) + "过桥,花费" + time[a] + "分钟");}}

(4)运行结果


0 0