题解
题目难度:hard
知识点:迷宫搜索类问题,利用BFS找到最短路径。
分析:
将人所在位置与箱子所在位置以及所走步数看作整体,新建节点Node。首先初始位置入队,通过移动不断将还没有经过的下一位置节点入队,直至找到箱子之前箱子的位置是不变的;当人找到箱子之后(即在箱子的一侧,上下左右),开始推箱子往另一侧走(下上右左),此时人和箱子的位置都开始移动,直至走到终点或无路可走结束。
本题可以分为2个过程:(具体实现思想见代码中注释)
① 人在找到箱子之前单独移动,箱子原地不动;在这个过程中,人要从“S”走到箱子“0”的旁边(上下左右)。
② 人找到箱子之后和箱子一起向“另一侧”移动,..S0.. -> ...S0. 。
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
public class Main {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
int m=sc.nextInt();
char[][] chas=new char[n][m];
// 人的起始位置S 以及箱子的位置
int startX=0,startY=0,boxX=0,boxY=0;
// 判断位置 ,即人要先找到箱子,再推着箱子往前走
for(int i=0;i<n;i++){
String string=sc.next();
for(int j=0;j<m;j++){
chas[i][j]=string.charAt(j);
if(chas[i][j]=='S'){
startX=i;
startY=j;
}
if(chas[i][j]=='0'){
boxX=i;
boxY=j;
}
}
}
System.out.println(solve(chas,startX,startY,boxX,boxY));
}
public static class Node{
int px; // 人的位置
int py;
int bx; //箱子的位置
int by;
int step; //从初始位置到现在节点所走的步数
public Node(int px,int py,int bx,int by){
this.px=px;
this.py=py;
this.bx=bx;
this.by=by;
}
}
private static int solve(char[][] chas,int startX, int startY,int boxX,int boxY) {
Node start=new Node(startX, startY,boxX,boxY);
int n=chas.length;
int m=chas[0].length;
// iswalked四维数组,可以用来存储走过的路径以防重复。
int[][][][] iswalked=new int[n][m][n][m];
// 每个节点都有dir4个方向的移动,分别是 下右上左
int[][] movedir=new int[][]{{1,0},{0,1},{-1,0},{0,-1}};
Queue<Node> que=new LinkedList<>(); //利用队列实现BFS
start.step=0;
que.add(start);
//开始BFS广度搜索最短路径
while(!que.isEmpty()){
Node cur=que.poll();
int newBx=cur.bx;
int newBy=cur.by;
for(int i=0;i<4;i++){ // 向4个方向走
//人在箱子左边或右边
if(cur.px==cur.bx){
if (cur.py+movedir[i][1]==cur.by){
newBy = cur.by+movedir[i][1];
}else{
newBy = cur.by;
}
}
//人在箱子上面或下面
if(cur.py==cur.by){
if(cur.px+movedir[i][0]==cur.bx){
newBx = cur.bx+movedir[i][0];
}else{
newBx = cur.bx;
}
}
// 箱子找到了要随人往4个方向动;没找到则箱子不动人动
Node next=new Node(cur.px+movedir[i][0], cur.py+movedir[i][1],newBx,newBy);
//不能让人在没找到箱子之前出地图或者自己提前到目的地
if(next.px<0||next.px>=n||next.py<0||next.py>=m||chas[next.px][next.py]=='#'
||next.bx<0||next.bx>=n||next.by<0||next.by>=m
||chas[next.bx][next.by]=='#'){
continue;
}
// 0说明这条路径没有走过
if(iswalked[next.px][next.py][next.bx][next.by]==0){
iswalked[next.px][next.py][next.bx][next.by]=1;
next.step=cur.step+1;
if(chas[next.bx][next.by]=='E'){ //此时把箱子推到终点了
return next.step; // 最先到终点的就是最短路径
}
que.add(next);
}
}
}
return -1;
}
}
京公网安备 11010502036488号