推箱子
思路
通过两次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;
}
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号