推箱子最短路径长度java实现

推箱子最短路径长度java实现


好的,在看完了c++版本之后,我终于徒手写完了java版。

其实就是队列实现的广度优先遍历,从初始点开始入队,主要是需要一个四维数组用于记录路径长度(非零则表示人箱的位置之前出现过,避免死循环),我觉得这个比较难想到。。。

ps. “判断人箱的位置之前是否出现过” 这段代码摆放的位置,应该在判断人是否踩在箱子代码之后吧。。

还有就是构造一个新的类型HumanBox(类似TreeNode)来作为入队元素。然后人的上下左右移动得到的新的HumanBox们 就类似树的左右结点。

结束标志就是队列为空,每次循环取出第一个元素。

如有错误可评论指出~

import java.util.ArrayList;
import java.util.Scanner;

public class PushPackage {

	public class HumanBox {
		int hx;
		int hy;
		int bx;
		int by;

		public HumanBox(int hx, int hy, int bx, int by) {
			super();
			this.hx = hx;
			this.hy = hy;
			this.bx = bx;
			this.by = by;
		}
	}

	public static void main(String[] args) {
		PushPackage pp = new PushPackage();
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();// n行
		int m = in.nextInt();// m列

		char[][] map = new char[n][m];

		int curhx = 0, curhy = 0, curbx = 0, curby = 0, endx = 0, endy = 0;

		int o=0;
		while(o<n) {
			String k = in.next();
			for (int j = 0; j < k.length(); j++) {
				map[o][j] = k.charAt(j);
				if (k.charAt(j) == 'X') {
					curhx = o;
					curhy = j;
				}
				if (k.charAt(j) == '*') {
					curbx = o;
					curby = j;
				}
				if (k.charAt(j) == '@') {
					endx = o;
					endy = j;
				}
			}
			o++;
		} // 构造地图矩阵
		
		

		int[] stepx = { 0, 0, -1, 1 };// 人的四个方向走位
		int[] stepy = { -1, 1, 0, 0 };

		int[][][][] count = new int[10][10][10][10];// 用于记录某个位置是否被访问过 以及记录长度
		count[curhx][curhy][curbx][curby] = 1;// 初始化位置为1

		ArrayList<HumanBox> queue = new ArrayList<HumanBox>();// 队列用于宽度优先搜索 第一个访问到的就是最短路径
		queue.add(pp.new HumanBox(curhx, curhy, curbx, curby));// 人和箱子的初始位置入队

		boolean re=false;
		while (queue.size() != 0) {// 结束条件一般是队列长度是否为零
			// 取出第一个元素
			HumanBox humanbox = queue.remove(0);
			if (humanbox.bx == endx && humanbox.by == endy) {
				// 箱子达到最终位置
				re=true;
				System.out.println(count[humanbox.hx][humanbox.hy][humanbox.bx][humanbox.by] - 1);// 因为初始化时1
				break;
			}
			// 人就开始走位了 一 一入队
			for (int i = 0; i < 4; i++) {
				int nhx = humanbox.hx + stepx[i];
				int nhy = humanbox.hy + stepy[i];
				// 人的新位置 接下来判断其合法性 以及是否踩在了箱子上
				if (nhx < 0 || nhy < 0 || nhx >= n || nhy >= m || map[nhx][nhy] == '#') {
					// 出界了 或者 有障碍
					continue; // 换个方向吧
				}
				
				/*//人来到了同一个地方?????    (*)
				if (count[nhx][nhy][humanbox.bx][humanbox.by] != 0) {
					// 此处来过了 换个位置吧
					continue;
				}*/
				
				
				if (nhx == humanbox.bx && nhy == humanbox.by) {
					// 踩在了箱子上 也就是把箱子也移动一下
					int nbx = humanbox.bx + stepx[i];
					int nby = humanbox.by + stepy[i];
					// 照样判断新箱子位置的合法性
					if (nbx < 0 || nby < 0 || nbx >= n || nby >= m || map[nbx][nby] == '#') {
						// 出界了 或者 有障碍
						continue; // 换个方向吧
					}
					if (count[nhx][nhy][nbx][nby] != 0) {
						// 此处来过了 换个位置吧
						continue;
					} else {
						// 此处没问题
						// 新的坐标入队 count标记一下
						queue.add(pp.new HumanBox(nhx, nhy, nbx, nby));
						count[nhx][nhy][nbx][nby]=count[humanbox.hx][humanbox.hy][humanbox.bx][humanbox.by]+1;
						continue;
					}
				}
				
				//人既没踩在箱子上 也没出界 也没遇到障碍
				
				//人来到了同一个地方?????   
				//这段代码放在这里就对了放在84行就不对。。。  可能是因为不能影响踩箱子的判断
				if (count[nhx][nhy][humanbox.bx][humanbox.by] != 0) {
					// 此处来过了 换个位置吧
					continue;
				}
				queue.add(pp.new HumanBox(nhx, nhy, humanbox.bx, humanbox.by));
				count[nhx][nhy][humanbox.bx][humanbox.by]=count[humanbox.hx][humanbox.hy][humanbox.bx][humanbox.by]+1;
			}

		}
		if(re==false) {
			System.out.println("-1");// 没有这条路径
		}

	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值