题解?

style 2020-07-24 11:22:45 2020-07-24 14:54:08

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring> 
using namespace std;

int n,m;
int x_e,y_e;//目的地(end) 
int x_m,y_m;//人的初始点(man) 
int x_b,y_b;//箱子的初始点(box) 

int bx[4]={1,-1,0,0};
int by[4]={0,0,1,-1};
char BX[4]={'S','N','E','W'};
 

int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};
char MX[4]={'n','s','w','e'};

char s[25][25];
bool vis[25][25][25][25];
bool vix[25][25];

//不能开一个全区变量来存答案,因为有多种状态,每种对应一种走法 
struct Node{
	int x_box,y_box;
	int x_man,y_man;
	string length; 
};//人推箱子时

struct man{
	int x,y;
	string z;
};//人自己走时

bool judge(int x,int y,int xx,int yy){//判断是否越界
	if(x<1||y<1||x>n||y>m||xx<1||yy<1||xx>n||yy>m) return true;
	return false;
}

string do_BFS(int x,int y,int ex,int ey,int bx,int by){
	memset(vix,0,sizeof(vix));//再次记忆化	
	
	queue<man> q1;
	man u;
	u.x=x, u.y=y, u.z="";
	q1.push(u);

	while(q1.size()){
		man w=q1.front(); q1.pop();
		for(int i=0;i<4;i++){
			int xx=w.x+dx[i];
			int yy=w.y+dy[i];
			if((xx==bx&& yy==by)||vix[xx][yy]||s[xx][yy]=='#') continue;
			if(xx<1||yy<1||xx>n||yy>m) continue;
			man p;
			p.x=xx, p.y=yy, p.z=w.z+MX[i];
			if(xx==ex && yy==ey) return p.z;
			q1.push(p);
			vix[xx][yy]=true;
		}
	} 
	return "No";
}

void BFS(){
	memset(vis,0,sizeof(vis));//箱子和人的位置(记忆化搜索 
	vis[x_b][y_b][x_m][y_m]=true; 
	
	queue<Node> q;
	Node v;
	v.x_box=x_b, v.y_box=y_b, v.x_man=x_m, v.y_man=y_m, v.length="";
	
	q.push(v);
	//也可以用构造函数
	//q.push( (Node){x_b,y_b,x_m,y_m,""} ); 
	
	while(q.size()){
		Node w=q.front(); q.pop();
		for(int i=0;i<4;i++){
			int xx=w.x_box+bx[i];
			int yx=w.y_box+by[i];
			int xm=w.x_box+dx[i];
			int ym=w.y_box+dy[i];//人可以推箱子的地点 
			
			if(judge(xx,yx,xm,ym) || vis[xx][yx][xm][ym] || s[xx][yx]=='#' || s[xm][ym]=='#') continue;
			string D="";
			if(xm!=w.x_man || ym!=w.y_man) D=do_BFS(w.x_man,w.y_man,xm,ym,w.x_box,w.y_box);
			//是w.x_box而不是xx;
			 
			if(D=="No") continue;
			vis[xx][yx][xm][ym]=true;
			
			Node v;
			v.x_box=xx, v.y_box=yx, v.x_man=w.x_box, v.y_man=w.y_box, v.length=w.length+D+BX[i];
			if(v.x_box==x_e && v.y_box==y_e){
				cout<<v.length<<endl;
				return;
			}
			q.push(v);
		}
	} 
	printf("Impossible.\n");
}

int main(){
	int t=0;
	while(scanf("%d%d",&n,&m) && n){
		t++;//第t组数据 
		for(int i=1;i<=n;i++){
			for(int j=1;j<=m;j++){
				cin>>s[i][j];//不能直接用scanf(因为有回车) 
				if(s[i][j]=='S') x_m=i,y_m=j;
				if(s[i][j]=='B') x_b=i,y_b=j;
				if(s[i][j]=='T') x_e=i,y_e=j;
			}
		}
		printf("Maze #%d\n",t);
		BFS();
		cout<<endl;
	}
	return 0;
}