推箱子
思路
通过两次bfs实现。
第一次判断人是否能从起点走到箱子所在位置的四周
第二次判断箱子是否能走到下一个位置
注意
箱子转弯时,人要绕到下一次推箱子的位置,若不能走到直接return
#include<bits/stdc++.h> //推箱子
#define ll long long
#define N 9
using namespace std;
int T,n,m,ans;
int px,py,sx,sy,dx,dy;
int a[N][N];
int vis[N][N]; //箱子在某点的方向
bool v[N][N]; // 人 不能走到1和箱子
bool f=0;
int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; //fx 1 2 3 4
struct node{
int x,y,step,fx;
};
bool che(int x,int y){ //箱子是否可走 //是否合法
if(x<1||y<1||x>n||y>m) return 0;
if(a[x][y]==1) return 0;
return 1;
}
bool check_p(int x,int y){ //人是否可走
if(x<1||y<1||x>n||y>m) return 0;
if(a[x][y]==1) return 0;
if(v[x][y]) return 0;
return 1;
}
bool bf(int ssx,int ssy,int ex,int ey,int xzx,int xzy){ //从a[ssx][ssy]走到a[ex][ey]且不经过a[xzx][xzy]
if(che(ssx,ssy)==0) return 0;
if(che(ex,ey)==0) return 0;
bool aa=0;
queue<node>q;
node now,next;
v[ssx][ssy]=1;
now.x=ssx;
now.y=ssy;
q.push(now);
while(!q.empty()){
now=q.front();
q.pop();
if(now.x==ex&&now.y==ey){
aa=1;
break;
}
for(int i=0;i<4;i++){
int xx=now.x+dir[i][0];
int yy=now.y+dir[i][1];
if(check_p(xx,yy)&&!(xx==xzx&&yy==xzy)){
v[xx][yy]=1;
next.x=xx;next.y=yy;
q.push(next);
}
}
}
return aa;
}
void bfs(int nowx,int nowy,int fx){ //箱子的位置,箱子的移动方向
vis[nowx][nowy]=fx;
queue<node>q;
node now,next;
now.x=nowx;
now.y=nowy;
now.fx=fx;
now.step=0;
q.push(now);
if(f==1) return;
while(!q.empty()){
now=q.front();
q.pop();
if(a[now.x][now.y]==3) {
f=1;
ans=now.step;
break;
}
for(int i=0;i<4;i++){
int xxx=now.x+dir[i][0],yyy=now.y+dir[i][1];
if(vis[xxx][yyy]==i+1) { continue; } //来过且方向一样
if(che(xxx,yyy)){ //没越界,不是墙
next.y=yyy;
next.x=xxx;
if(now.fx==i+1){ //接下来判断人能不能这样推箱子
next.fx=i+1;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
else{ //换方向 上下变左右,左右变上下
if(now.fx==1){
if(i+1==3){
memset(v,0,sizeof(v));
if(bf(now.x+1,now.y,now.x,now.y+1,now.x,now.y)){ //不能走到 1和 a[now.x][now.y]
next.fx=3;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
if(i+1==4){
memset(v,0,sizeof(v));
if(bf(now.x+1,now.y,now.x,now.y-1,now.x,now.y)){
next.fx=4;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
if(i+1==2){
memset(v,0,sizeof(v));
if(bf(now.x+1,now.y,now.x-1,now.y,now.x,now.y)){
next.fx=2;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
}
if(now.fx==2){
if(i+1==1){
memset(v,0,sizeof(v));
if(bf(now.x-1,now.y,now.x+1,now.y,now.x,now.y)){
next.fx=1;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
if(i+1==3){
memset(v,0,sizeof(v));
if(bf(now.x-1,now.y,now.x,now.y+1,now.x,now.y)){
next.fx=3;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
if(i+1==4){
memset(v,0,sizeof(v));
if(bf(now.x-1,now.y,now.x,now.y-1,now.x,now.y)){
next.fx=4;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
}
if(now.fx==3){
if(i+1==4){
memset(v,0,sizeof(v));
if(bf(now.x,now.y+1,now.x,now.y-1,now.x,now.y)){
next.fx=4;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
if(i+1==1){
memset(v,0,sizeof(v));
if(bf(now.x,now.y+1,now.x+1,now.y,now.x,now.y)){
next.fx=1;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
if(i+1==2){
memset(v,0,sizeof(v));
if(bf(now.x,now.y+1,now.x-1,now.y,now.x,now.y)){
next.fx=2;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
}
if(now.fx==4){
if(i+1==3){
memset(v,0,sizeof(v));
if(bf(now.x,now.y-1,now.x,now.y+1,now.x,now.y)){
next.fx=3;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
if(i+1==1){
memset(v,0,sizeof(v));
if(bf(now.x,now.y-1,now.x+1,now.y,now.x,now.y)){
next.fx=1;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
if(i+1==2){
memset(v,0,sizeof(v));
if(bf(now.x,now.y-1,now.x-1,now.y,now.x,now.y)){
next.fx=2;
next.step=now.step+1;
vis[xxx][yyy]=i+1;
q.push(next);
}
}
}
}
}
}
}
if(f==1) return;
}
int main(){
scanf("%d",&T);
while(T--){
f=0;
ans=0;
memset(a,-1,sizeof(a));
memset(v,0,sizeof(v));
memset(vis,0,sizeof(vis));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&a[i][j]);
if(a[i][j]==4) px=i,py=j;
if(a[i][j]==2) sx=i,sy=j;
if(a[i][j]==3) dx=i,dy=j;
}
}
memset(v,0,sizeof(v));
if(bf(sx-1,sy,px,py,sx,sy)){ //不能走到 1和 2
memset(vis,0,sizeof(vis));
bfs(sx,sy,2);
}
if(f==1) {
printf("%d\n",ans);
continue;
}
memset(v,0,sizeof(v));
if(bf(sx+1,sy,px,py,sx,sy)){
memset(vis,0,sizeof(vis));
bfs(sx,sy,1);
}
if(f==1) {
printf("%d\n",ans);
continue;
}
memset(v,0,sizeof(v));
if(bf(sx,sy-1,px,py,sx,sy)){
memset(vis,0,sizeof(vis));
bfs(sx,sy,4);
}
if(f==1) {
printf("%d\n",ans);
continue;
}
memset(v,0,sizeof(v));
if(bf(sx,sy+1,px,py,sx,sy)){
memset(vis,0,sizeof(vis));
bfs(sx,sy,3);
}
if(f==1) {
printf("%d\n",ans);
continue;
}
if(f==0) puts("-1");
}
return 0;
}