YbtOJ 广度搜索课堂过关 例3 立体推箱子【bfs】

在这里插入图片描述


思路

首先这个是广搜。
可以预处理出刚开始的箱子状态和终点。
那么 1 × 2 1\times 2 1×2 的情况怎么记录呢?
我们可以记录第一个格子,然后直接把第二个格子判断状态即可。
然后对于箱子的移动很麻烦,我们要用 d x , d y , d t dx,dy,dt dx,dy,dt 分别表示每种情况下的移动方式。
最后直接搜就好了。

C o d e Code Code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int dx[4][5]={
    
    {
    
    },{
    
    0,0,1,0,-2},{
    
    0,0,1,0,-1},{
    
    0,0,2,0,-1}};
const int dy[4][5]={
    
    {
    
    },{
    
    0,1,0,-2,0},{
    
    0,2,0,-1,0},{
    
    0,1,0,-1,0}};
const int dt[4][5]={
    
    {
    
    },{
    
    0,2,3,2,3},{
    
    0,1,2,1,2},{
    
    0,3,1,3,1}};
int v[510][510][4];
char a[510][510],c;
int n,m,tx,ty;
struct node
{
    
    
	int x,y,t,c;
}f[10001000];
bool check(int x,int y,int t)
{
    
    
	if(x<1||x>n||y<1||y>m||v[x][y][t]==1)
	  return 0;
	if(t==1)
	 {
    
    
	 	if(a[x][y]=='E'||a[x][y]=='#')
	 	  return 0;
	 }
	if(t==3)
	 {
    
    
	 	if(a[x][y]=='#'||x+1>n||a[x+1][y]=='#')
	 	  return 0;
	 }
	if(t==2)
	 {
    
    
	 	if(a[x][y]=='#'||y+1>m||a[x][y+1]=='#')
	 	  return 0;
	 }
	return 1;
}
void bfs()
{
    
    
	int hd=0,tl=1;
	while(hd<tl)
	 {
    
    
	 	hd++;
	 	for(int i=1; i<=4; i++)
	 	 {
    
    
	 	 	int xx=f[hd].x+dx[f[hd].t][i];
	 	 	int yy=f[hd].y+dy[f[hd].t][i];
	 	 	int tt=dt[f[hd].t][i];
	 	 	if(check(xx,yy,tt))
	 	 	 {
    
    
	 	 	 	tl++;
	 	 	 	f[tl]=(node){
    
    xx,yy,tt,f[hd].c+1};
	 	 	 	if(xx==tx&&yy==ty&&tt==1)
	 	 	 	 {
    
    
	 	 	 	 	cout<<f[tl].c<<endl;
	 	 	 	 	return;
				 }
				v[xx][yy][tt]=1;
			 }
		 }
	 }
	cout<<"Impossible"<<endl;
}
void ycl()
{
    
    
	int w=0;
	for(int i=1; i<=n; i++)
	 for(int j=1; j<=m; j++)
	  {
    
    
	  	if(a[i][j]=='X'&&w==0)
	  	 {
    
    
	  	 	w=1;
	  	 	if(a[i][j+1]=='X')
	  	 	  f[1].x=i,f[1].y=j,f[1].t=2;
	  	 	else if(a[i+1][j]=='X')
	  	 	  f[1].x=i,f[1].y=j,f[1].t=3;
	  	 	else
	  	 	  f[1].x=i,f[1].y=j,f[1].t=1;
	  	 	v[i][j][f[1].t]=1;
		 }
		if(a[i][j]=='O')
		  tx=i,ty=j;
	  }
}
int main()
{
    
    
	while(cin>>n>>m)
	 {
    
    
	   memset(v,0,sizeof(v));
	   if(n==0&&m==0)
	     break;
	   for(int i=1; i<=n; i++)
	    for(int j=1; j<=m; j++)
	     {
    
    
	  	    a[i][j]=getchar();
	  	    while(a[i][j]!='#'&&a[i][j]!='X'&&a[i][j]!='.'&&a[i][j]!='O'&&a[i][j]!='E')
	  	      a[i][j]=getchar();
	     }
	   ycl();
	   bfs();
	 }
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Jackma_mayichao/article/details/112388561
今日推荐