C++:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>
#include <queue>
#define INF 0x3f3f3f3f
using namespace std;
//0空位 1墙 2起点 3终点 4人的起点
int m,n;
int graph[10][10],vis[10][10][10][10];
int dx[] = {0,0,1,-1};
int dy[] = {1,-1,0,0};
struct Point{
int x,y;
int x_box,y_box,step; //箱子及其已经使用够的步数
}p;
int bfs(){
Point cur,next;
queue<Point> q;
q.push(p);
int res = INF;
vis[p.x][p.y][p.x_box][p.y_box] = true; //初值为INF
while(!q.empty()){
cur = q.front();
q.pop();
if(graph[cur.x_box][cur.y_box]==3){ //箱子达到了终点
res = min(res,cur.step);
}
for(int i=0;i<4;i++){
next = cur;
next.x += dx[i];
next.y += dy[i]; //推箱子,移动的是人
if(next.x>=0 && next.x<m && next.y>=0 && next.y<n && graph[next.x][next.y]!=1 && next.step<vis[next.x][next.y][next.x_box][next.y_box]){ //判断人的位置是否合法
if(next.x==next.x_box && next.y==next.y_box){
next.x_box += dx[i];
next.y_box += dy[i];
next.step++;
if(next.x_box>=0 && next.x_box<m && next.y_box>=0 && next.y_box<n && graph[next.x_box][next.y_box]!=1 && next.step<vis[next.x][next.y][next.x_box][next.y_box]){
vis[next.x][next.y][next.x_box][next.y_box] = next.step;
q.push(next);
}
}
else{
vis[next.x][next.y][next.x_box][next.y_box] = next.step;
q.push(next); //此时箱子没动,不需要更新箱子的step,直接入队
}
}
}
}
return res;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
memset(vis,INF,sizeof(vis));
scanf("%d%d",&m,&n);
for(int i=0;i<m;i++)
for(int j=0;j<n;j++){
scanf("%d",&graph[i][j]);
if(graph[i][j]==4){ //人的起点
p.x = i;
p.y = j;
p.step = 0;
}
else if(graph[i][j]==2){
p.x_box = i;
p.y_box = j;
}
}
int res = bfs();
if(res==INF)
res = -1;
printf("%d\n",res);
}
return 0;
}
JAVA:
import java.util.*;
//0空格 1墙 2箱子起点 3箱子终点 4人起点
public class HDU1254 {
public static class Point{
public int x,y,x_box,y_box,step;
Point(){
}
Point(Point p){
x = p.x;
y = p.y;
x_box = p.x_box;
y_box = p.y_box;
step = p.step;
}
}
public static int[] dx = {0,0,1,-1};
public static int[] dy = {1,-1,0,0};
public static int INF = 0x3f3f3f3f;
public static int m,n;
public static int[][] graph;
public static int[][][][] vis;
public static Point p0;
public static int bfs() {
int res = Integer.MAX_VALUE;
Point cur,next;
Queue<Point> q = new LinkedList<>();
vis[p0.x][p0.y][p0.x_box][p0.y_box] = 1;
q.offer(p0);
while(!q.isEmpty()) {
cur = q.poll();
if(graph[cur.x_box][cur.y_box]==3) {
res = Math.min(res, cur.step); //判断箱子是否到达了终点
}
for(int i=0;i<4;i++) { //移动人的位置
next = new Point(cur);
next.x += dx[i];
next.y += dy[i];
if(next.x>=0 && next.x<m && next.y>=0 && next.y<n && graph[next.x][next.y]!=1 &&
next.step<vis[next.x][next.y][next.x_box][next.y_box]) {
if(next.x==next.x_box && next.y==next.y_box) {
//人走到箱子的位置上了,重合了。重合之后,箱子能推动,才能表示一个新的状态
next.x_box += dx[i];
next.y_box += dy[i];
next.step++;
if(next.x_box>=0 && next.x_box<m && next.y_box>=0 && next.y_box<n
&& graph[next.x_box][next.y_box]!=1
&& next.step<vis[next.x][next.y][next.x_box][next.y_box]) {
vis[next.x][next.y][next.x_box][next.y_box] = next.step;
q.offer(next);
}
}
else {
vis[next.x][next.y][next.x_box][next.y_box] = next.step;
q.offer(next);
}
}
}
}
return res;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
while(T-->0) {
m = sc.nextInt();
n = sc.nextInt();
graph = new int[10][10];
vis = new int[10][10][10][10];
// Arrays.fill(vis, Integer.MAX_VALUE);
for(int i=0;i<10;i++)
for(int j=0;j<10;j++)
for(int k=0;k<10;k++)
for(int l=0;l<10;l++)
vis[i][j][k][l] = Integer.MAX_VALUE;
p0 = new Point();
for(int i=0;i<m;i++)
for(int j=0;j<n;j++) {
graph[i][j] = sc.nextInt();
if(graph[i][j]==4) {
p0.x = i;
p0.y = j;
p0.step = 0;
}
else if(graph[i][j]==2) {
p0.x_box = i;
p0.y_box = j;
}
}
int res = bfs();
if(res==Integer.MAX_VALUE)
res = -1;
System.out.println(res);
}
}
}