题目链接:hdu1254
/*
用广搜寻找最小步数,推箱子需要满足以下几个条件:
1.人能走到推箱子的那个位置
2.人不能穿过箱子.
3.箱子可以回到前一状态的位置,但不是同一方向回到的
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <queue>
using namespace std;
int d[4][2] = {{1,0},{0,1},{-1,0},{0,-1}};
int map[8][8];
int v[8][8][5];//第三维表示箱子在(i,j)时,是由哪个方向推过来的
int flag;
int n,m,ex,ey,sx,sy,rx,ry;
struct node
{
int x, y;
int step;
int rx, ry;//表示箱子在(x,y)时,箱子之前的位置,也就是人推完箱子后,站在箱子原来的位置
friend bool operator < (node a,node b)
{
return a.step > b.step;
}
};
bool judge(int x, int y)
{
if(x < 0 || x >= n || y < 0 || y >= m) return true;
return false;
}
int p_bfs(int sx, int sy, int ex, int ey, int jx, int jy)
{
bool f[8][8];
memset(f, false, sizeof(f));
priority_queue <node> q;
node s, tmp;
s.x = sx;
s.y = sy;
f[sx][sy] = true;
s.step = 0;
q.push(s);
while(!q.empty())
{
tmp = q.top();
q.pop();
if(tmp.x == ex && tmp.y == ey)
return 1;
for(int i = 0; i < 4; i ++)
{
s.x = tmp.x + d[i][0];
s.y = tmp.y + d[i][1];
if(f[s.x][s.y]) continue;
if(judge(s.x, s.y) || map[s.x][s.y] == 1 || (s.x == jx && s.y == jy)) continue;//不能穿过箱子
s.step = tmp.step + 1;
f[s.x][s.y] = true;
q.push(s);
}
}
return 0;
}
void bfs()
{
memset(v, -1, sizeof(v));
priority_queue <node> q;
node s, tmp;
s.x = sx;
s.y = sy;
s.rx = rx;
s.ry = ry;
s.step = 0;
q.push(s);
while(!q.empty())
{
tmp = q.top();
q.pop();
if(tmp.x == ex && tmp.y == ey)
{
flag = true;
printf("%d\n",tmp.step);
return ;
}
for(int i = 0; i < 4; i ++)
{
s.x = tmp.x + d[i][0];
s.y = tmp.y + d[i][1];
if(v[s.x][s.y][i] == i) continue;
if(judge(s.x, s.y) || map[s.x][s.y] == 1) continue;
int dx = tmp.x - d[i][0];//dx,dy表示人要推箱子时站的位置
int dy = tmp.y - d[i][1];
if(judge(dx, dy) || map[dx][dy] == 1) continue;//判断位置是否越界,或该位置是墙
if(p_bfs(tmp.rx, tmp.ry, dx, dy, tmp.x, tmp.y))
{
s.rx = tmp.x;
s.ry = tmp.y;
s.step = tmp.step + 1;
v[s.x][s.y][i] = i;
q.push(s);
}
}
}
}
int main()
{
int T,i,j;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(i = 0; i < n; i ++)
for(j = 0; j < m; j ++)
{
scanf("%d",&map[i][j]);
if(map[i][j] == 2) sx = i, sy = j;
else if(map[i][j] == 3) ex = i, ey = j;
else if(map[i][j] == 4) rx = i, ry = j;
}
flag = 0;
bfs();
if(!flag) puts("-1");
}
return 0;
}