立体推箱子
题目链接:立体推箱子
题目描述


解题思路
这道题很容易可以想到是广搜。
难点在于如何表示出躺下的情况。
但其实只需要记录两个点中的一个,然后用一个状态变量就可以表示出一整个箱子。
主要是状态的转移不太好推,要有耐心。
其他的注意一些细节就可以了。
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;
}
}

这篇博客主要介绍了立体推箱子问题的解决思路,利用广度优先搜索(BFS)策略来求解。文章提到难点在于状态表示,通过记录箱子的一个点和状态变量来简化表示。在搜索过程中,检查每个位置是否合法,并更新状态。通过实例展示了解题过程,包括状态转移的细节。最后提供了一个完整的C++代码实现,包括关键函数和输入处理。
296





