立体推箱子
题目链接:立体推箱子
题目描述
解题思路
这道题很容易可以想到是广搜。
难点在于如何表示出躺下的情况。
但其实只需要记录两个点中的一个,然后用一个状态变量就可以表示出一整个箱子。
主要是状态的转移不太好推,要有耐心。
其他的注意一些细节就可以了。
code
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int xn[4][5]={
{
},{
0,-1,0,2,0},{
0,-1,0,1,0},{
0,-2,0,1,0}};
const int yn[4][5]={
{
},{
0,0,2,0,-1},{
0,0,1,0,-2},{
0,0,1,0,-1}};
const int tn[4][5]={
{
},{
0,3,2,3,2},{
0,2,1,2,1},{
0,1,3,1,3}};
int n,m;
int ex,ey;
int v[510][510][5];
char a[510][510];
struct abc{
int x,y,t,s;
}f[2500010];
bool check(int x,int y,int t)
{
if(x<1||x>n||y<1||y>m)
return 0;
if(t==1)
{
if(a[x][y]=='E')
return 0;
if(a[x][y]=='#')
return 0;
}
if(t==2)
{
if(a[x][y]=='#')
return 0;
if(a[x][y-1]=='#')
return 0;
}
if(t==3)
{
if(a[x][y]=='#')
return 0;
if(a[x-1][y]=='#')
return 0;
}
return 1;
}
bool bfs()
{
int hd=0,tl=1;
while(hd<tl)
{
hd++;
for(int i=1;i<=4;i++)
{
int x=f[hd].x+xn[f[hd].t][i];
int y=f[hd].y+yn[f[hd].t][i];
int t=tn[f[hd].t][i];
if(check(x,y,t)&&!v[x][y][t])
{
v[x][y][t]=1;
f[++tl]=(abc){
x,y,t,f[hd].s+1};
if(x==ex&&y==ey&&t==1)
{
cout<<f[tl].s<<endl;
return 0;
}
}
}
}
return 1;
}
void star()
{
memset(v,0,sizeof(v));
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(a[i][j]=='X')
{
f[1].x=i,f[1].y=j,f[1].s=0;
if(a[i][j-1]=='X')
f[1].t=2;
else if(a[i-1][j]=='X')
f[1].t=3;
else
f[1].t=1;
v[i][j][f[1].t]=1;
}
if(a[i][j]=='O')
ex=i,ey=j;
}
}
int main()
{
while(cin>>n>>m)
{
if(n==0&&m==0)
return 0;
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]!='.'&&a[i][j]!='X'&&a[i][j]!='E'&&a[i][j]!='O')
a[i][j]=getchar();
}
}
star();
if(bfs())
cout<<"Impossible"<<endl;
}
}