推箱子最短路径长度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");// 没有这条路径
}
}
}