题目链接:点击查看
题目大意:模拟Bloxorz小游戏找出最优解,简单说一下规则,给出一个n*m的矩阵,其中,"#"代表墙,"X"代表起点,"O"代表终点,"E"代表脆弱道路,即承受不住立着的方块,"."代表普通道路
题目分析:因为方块总共有三种状态:立着(占1格)、竖着(占2格)、横着(占2格),我们可以将占两个的两个状态压缩到一格中,竖着的(上下分布)我们规定有效方格在上面,横着的(左右分布)我们规定有效方格在左面,在转移状态时,立着的状态可以直接判断转移,其余两种状态需要判断两个方格是否同时满足条件才可以进行转移,我们在储存状态时用的结构体包含了四个变量:x,y,flag,step,分别代表横坐标,纵坐标,状态,和步数,而每种情况转移时都有4种不同的方案,所以方向函数需要写三个,并且每次转移时需要根据当前的状态分类讨论,细心一点认真写一下bfs就能A了,具体的细节写在代码中了,上代码:
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
const int inf=0x3f3f3f3f;
const int N=510;
char maze[N][N];
bool vis[N][N][3];
int n,m,ans;
//规定立着的状态为0,横着的状态为1,竖着的状态为2
const int b0[4][2]={0,-2,-2,0,0,1,1,0};//立着 flag=0 1,2,1,2
const int b1[4][2]={1,0,-1,0,0,-1,0,2};//横着 flag=1 1,1,0,0
const int b2[4][2]={0,-1,0,1,-1,0,2,0};//竖着 flag=2 2,2,0,0
struct Node
{
int x,y,step,flag;
Node(int X,int Y,int STEP,int FLAG)
{
x=X;
y=Y;
step=STEP;
flag=FLAG;
}
};
bool check(int x,int y)
{
if(x<0||y<0||x>=n||y>=m)
return false;
return true;
}
bool bfs()
{
memset(vis,false,sizeof(vis));
queue<Node>q;
for(int i=0;i<n;i++)//找一下起点
for(int j=0;j<m;j++)
if(maze[i][j]=='X')
{
if(check(i,j+1)&&maze[i][j+1]=='X')//如果起点是横着两个X
{
q.push(Node(i,j,0,1));
vis[i][j][1]=true;
}
else if(check(i+1,j)&&maze[i+1][j]=='X')//如果起点是竖着两个X
{
q.push(Node(i,j,0,2));
vis[i][j][2]=true;
}
else//如果起点是立着的一个X
{
q.push(Node(i,j,0,0));
vis[i][j][0]=true;
}
goto start;//用goto函数跳出两层for循环
}
start:
while(!q.empty())
{
Node cur=q.front();
q.pop();
// cout<<cur.x<<' '<<cur.y<<endl;
if(maze[cur.x][cur.y]=='O'&&cur.flag==0)
{
ans=cur.step;
return true;
}
if(cur.flag==0)//若当前状态立着
{
for(int i=0;i<4;i++)
{
int xx=cur.x+b0[i][0];
int yy=cur.y+b0[i][1];
if(i==0||i==2)//flag=1
{
if(!check(xx,yy)||!check(xx,yy+1)||vis[xx][yy][1]||maze[xx][yy]=='#'||maze[xx][yy+1]=='#')
continue;
vis[xx][yy][1]=true;
q.push(Node(xx,yy,cur.step+1,1));
}
else if(i==1||i==3)//flag=2
{
if(!check(xx,yy)||!check(xx+1,yy)||vis[xx][yy][2]||maze[xx][yy]=='#'||maze[xx+1][yy]=='#')
continue;
vis[xx][yy][2]=true;
q.push(Node(xx,yy,cur.step+1,2));
}
}
}
else if(cur.flag==1)//若当前状态横着
{
for(int i=0;i<4;i++)
{
int xx=cur.x+b1[i][0];
int yy=cur.y+b1[i][1];
if(i==0||i==1)//flag=1
{
if(!check(xx,yy)||!check(xx,yy+1)||vis[xx][yy][1]||maze[xx][yy]=='#'||maze[xx][yy+1]=='#')
continue;
vis[xx][yy][1]=true;
q.push(Node(xx,yy,cur.step+1,1));
}
else if(i==2||i==3)//flag=0
{
if(!check(xx,yy)||vis[xx][yy][0]||maze[xx][yy]=='#'||maze[xx][yy]=='E')
continue;
vis[xx][yy][0]=true;
q.push(Node(xx,yy,cur.step+1,0));
}
}
}
else if(cur.flag==2)//若当前状态竖着
{
for(int i=0;i<4;i++)
{
int xx=cur.x+b2[i][0];
int yy=cur.y+b2[i][1];
if(i==0||i==1)//flag=2
{
if(!check(xx,yy)||!check(xx+1,yy)||vis[xx][yy][2]||maze[xx][yy]=='#'||maze[xx+1][yy]=='#')
continue;
vis[xx][yy][2]=true;
q.push(Node(xx,yy,cur.step+1,2));
}
else if(i==2||i==3)//flag=0
{
if(!check(xx,yy)||vis[xx][yy][0]||maze[xx][yy]=='#'||maze[xx][yy]=='E')
continue;
vis[xx][yy][0]=true;
q.push(Node(xx,yy,cur.step+1,0));
}
}
}
}
return false;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF&&n+m)
{
for(int i=0;i<n;i++)
scanf("%s",maze[i]);
if(bfs())
printf("%d\n",ans);
else
printf("Impossible\n");
}
return 0;
}