[Ybtoj 고효율 고급 1.5] [Wide Search] 입체 상자 더미
이야기
문제 해결 아이디어
직육면체의 세 위치를
기록하고 똑바로 서있을 때만 자신을 기록하고, 바닥을 수직으로 기록하고, 오른쪽을 수평으로 기록합니다.
이 세 가지 상황에서 위, 아래, 왼쪽 및 오른쪽을 밀고 있습니다. 어떤 상태를 위로 밀고, 아래, 왼쪽, 오른쪽?
Classic Guangsou가 다시 실행했습니다.
암호
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
struct lzf{
int x,y,t,b;
}q[1000100];
char c;
int n,m,h,t,zx,zy,a[520][520],p[520][520][4];
int fx[4][5]={
{
},{
0,-1,0,2,0},{
0,-2,0,1,0},{
0,-1,0,1,0}};
int fy[4][5]={
{
},{
0,0,2,0,-1},{
0,0,1,0,-1},{
0,0,1,0,-2}}; //坐标的变化
int ft[4][5]={
{
},{
0,2,3,2,3},{
0,1,2,1,2},{
0,3,1,3,1}}; //状态的变化
bool check(int xx,int yy,int tt)
{
if (xx<1||xx>n||yy<1||yy>m) return 0;
if (tt==1&&a[xx][yy]==0) return 1; //只有一个立着,不可以在易碎面上
if (tt==2&&a[xx][yy]!=1&&a[xx-1][yy]!=1&&xx-1>0) return 1; //竖着,两个都不能是禁地
if (tt==3&&a[xx][yy]!=1&&a[xx][yy-1]!=1&&yy-1>0) return 1; //横着,两个也不能是禁地
return 0;
}
bool dfs()
{
do{
h++;
for (int i=1;i<=4;i++)
{
int xx=q[h].x+fx[q[h].t][i],yy=q[h].y+fy[q[h].t][i],tt=ft[q[h].t][i];
if (check(xx,yy,tt)&&!p[xx][yy][tt]) //可以走,且没走过
{
q[++t].x=xx;
q[t].y=yy;
q[t].t=tt;
q[t].b=q[h].b+1;
p[xx][yy][tt]=1; //进队
if (xx==zx&&yy==zy&&q[t].t==1)
{
printf("%d\n",q[t].b);
return 0;
}
}
}
} while (h<t);
return 1;
}
int main()
{
while (1)
{
scanf("%d%d",&n,&m);
if (!n&&!m) break;
h=0,t=1;
int vis=0;
memset(a,0,sizeof(a));
memset(q,0,sizeof(q));
memset(p,0,sizeof(p));
q[t].t=1;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
cin>>c;
if (c=='#') a[i][j]=1;
if (c=='E') a[i][j]=-1;
if (c=='O') zx=i,zy=j,a[i][j]=0;
if (c=='X')
{
if (vis)
if (q[t].x+1==i&&q[t].x)
q[t].t=2;
else q[t].t=3; //更改起始点的状态
q[t].x=i;
q[t].y=j;
vis=1;
} //预处理
}
p[q[t].x][q[t].y][q[t].t]=1;
if (dfs()) printf("Impossible\n");
}
return 0;
}