题面描述
一个游戏,为一个
N
N
N行
M
M
M列第二矩阵,位置可能是硬地("
.
.
.")、易碎地面(“
E
E
E”)、禁地("#")、起点(“
X
X
X”)或终点(“
O
O
O”).你的任务是操作一个
1
∗
1
∗
2
1*1*2
1∗1∗2的长方体。这个长方体在地面上有两种放置形式.“立”(占
1
∗
1
1*1
1∗1),“躺”(占
1
∗
2
1*2
1∗2)。每一步操作中,可以按上下左右四个键之一。按下任意键,可以使长方体向对应方向沿着棱滚动
90
°
90°
90°
有以下禁忌
- 不能有任何部位接触“#”
- 不能有立在“ E E E”的情况
图中可能有两个“
X
X
X”的情况,目标:求出滚动到“
O
O
O”的步数,如果不能则输出“
I
m
p
o
s
s
i
b
l
e
Impossible
Impossible”
数据范围:
3
≤
N
,
M
≤
500
3≤N,M≤500
3≤N,M≤500.
思路
其实挺好想的,就是看自己愿不愿意下功夫。
本文代码用了三元组
(
x
,
y
,
l
i
e
)
(x,y,lie)
(x,y,lie),
来表示当
l
i
e
=
0
lie=0
lie=0时,即为立起来时,位置为
(
x
,
y
)
(x,y)
(x,y).
l
i
e
=
1
lie=1
lie=1时,即为横躺着,左半部分的位置为
(
x
,
y
)
(x,y)
(x,y).
l
i
e
=
2
lie=2
lie=2时,即为竖躺着,上半部分的位置为
(
x
,
y
)
(x,y)
(x,y)
手动模拟一下
得出
const int next_x[3][4]={{0,0,-2,1},{0,0,-1,1},{0,0,-1,2}};
const int next_y[3][4]={{-2,1,0,0},{-1,2,0,0},{-1,1,0,0}};
const int next_lie[3][4]={{1,1,2,2},{0,0,1,1},{2,2,0,0}};
0~3分别表示左、右、上、下方向
解释一下
n
e
x
t
x
[
i
]
[
j
]
next_x[i][j]
nextx[i][j]即处于
l
i
e
=
i
方
向
为
j
滚
动
lie=i~~方向为j滚动
lie=i 方向为j滚动的x增减状态,
以此类推。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstdlib>
using namespace std;
const int dx[4]={0,0,1,-1},dy[4]={1,-1,0,0};
const int next_x[3][4]={{0,0,-2,1},{0,0,-1,1},{0,0,-1,2}};
const int next_y[3][4]={{-2,1,0,0},{-1,2,0,0},{-1,1,0,0}};
const int next_lie[3][4]={{1,1,2,2},{0,0,1,1},{2,2,0,0}};
struct node
{
int x,y,lie;//lie==0立着,lie==1横着躺,lie==2竖着躺
node(){};
node(int x,int y,int lie):x(x),y(y),lie(lie){}
};
char s[510][510];
node st,ed;
int n,m,d[510][510][3];
queue<node>q;
bool valid(int x,int y)
{
return x>=1&&x<=n&&y>=1&&y<=m;
}
bool valid(node next)
{
if(!valid(next.x,next.y))return 0;
int x=next.x,y=next.y,lie=next.lie;
if(s[x][y]=='#')return 0;
if(s[x][y]!='.'&&!lie)return 0;
if(lie==1&&s[x][y+1]=='#')return 0;
if(lie==2&&s[x+1][y]=='#')return 0;
return 1;
}
void pre()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
if(s[i][j]=='O')ed.x=i,ed.y=j,ed.lie=0,s[i][j]='.';
else if(s[i][j]=='X')
{
for(int k=0;k<4;k++)
{
int x=dx[k]+i,y=dy[k]+j;
if(s[x][y]=='X'&&valid(x,y))
{
st.x=min(i,x),st.y=min(j,y);
st.lie=k<2?1:2;
s[i][j]=s[x][y]='.';
break;
}
if(s[i][j]=='X')st.x=i,st.y=j,st.lie=0,s[i][j]='.';
}
}
}
}
int bfs()
{
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=0;k<3;k++)d[i][j][k]=-1;
while(q.size())q.pop();
d[st.x][st.y][st.lie]=0;q.push(st);
while(!q.empty())
{
node t=q.front();q.pop();
for(int i=0;i<4;i++)
{
node next=t;
next.x+=next_x[next.lie][i];
next.y+=next_y[next.lie][i];
next.lie=next_lie[next.lie][i];
if(!valid(next))continue;
if(d[next.x][next.y][next.lie]==-1)
{
d[next.x][next.y][next.lie]=d[t.x][t.y][t.lie]+1;
q.push(next);
if(next.x==ed.x&&next.y==ed.y&&next.lie==ed.lie)return d[next.x][next.y][next.lie];
}
if(d[ed.x][ed.y][ed.lie]!=-1)return d[ed.x][ed.y][ed.lie];
}
}
return -1;
}
int main()
{
while(scanf("%d%d",&n,&m)&&n)
{
for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
pre();
int ans=bfs();
if(ans==-1)puts("Impossible");else printf("%d\n",ans);
}
return 0;
}