过河问题的代码实现

问题描述

在漆黑的夜里,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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值