描述
玉米田迷宫是一种受欢迎的万圣节款待。参观者可以看到入口,必须在面对僵尸,电锯挥舞的精神病患者,嬉皮士和其他恐怖的迷宫中漫步,寻找出口。
一种流行的迷宫步行策略可确保访客最终找到出口。只需选择右侧或左侧墙壁,然后按照它即可。当然,不能保证哪种策略(左或右)会更好,而且所采用的路径很少是最有效的。(它也不适用于不在边缘的出口的迷宫;这个类型的迷宫没有在这个问题中表示。)
作为即将被转换为迷宫的玉米田的主人,你想要一个能够确定左右路径以及最短路径的计算机程序,以便你可以找出哪个布局具有混淆游客的最佳机会。
输入
对此问题的输入将以包含单个整数n的行开始,该整数n表示迷宫的数量。每个迷宫将由一条宽度为w,高度为h的线组成(3 <= w,h <= 40),然后是h行w字符,每行代表迷宫布局。墙由散列标记('#')表示,空格按句点('。')表示,开头用'S'表示,退出用'E'表示。
正好一个'S'和一个'E'将出现在迷宫中,它们将始终位于迷宫边缘之一,而不是一个角落。迷宫将被墙壁('#')完全包围,唯一的开口是'S'和'E'。'S'和'E'也将被至少一个墙('#')隔开。
产量
对于输入中的每个迷宫,在单行上输出一个人将(按顺序)左,右和最短路径访问(包括'S'和'E')的(不一定是唯一的)方格的数量,每个单独的空格分隔。只允许在水平或垂直方向上从一个方格移动到另一个方格; 沿着对角线的运动是不允许的。
样本输入
2 8 8 ######## #......# #.####.# #.####.# #.####.# #.####.# #...#..# #S#E#### 9 5 ######### #.#.#.#.# S.......E #.#.#.#.# #########
Sample Output
37 5 5 17 17 9
左转优先和右转优先用的深搜,最短路径用的广搜
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
int x,y,ex,ey;
struct zuobiao
{
int x,y;
}now,nex;
int m,n;
int step,step2;
char a[50][50];
int mark[50][50];
int output[50][50];
int vis[50][50];
int fx[4]={0,0,-1,1};
int fy[4]={1,-1,0,0};
int bfs(int x,int y)
{
memset(output,0,sizeof(output));
memset(vis,0,sizeof(vis));
vis[x][y]=1;
queue<zuobiao >s;
now.x=x;
now.y=y;
output[x][y]=1;
s.push(now);
while(!s.empty())
{
now=s.front();
if(a[now.x][now.y]=='E')
{
return output[now.x][now.y];
}
s.pop();
for(int i=0;i<4;i++)
{
nex.x=now.x+fx[i];
nex.y=now.y+fy[i];
if(nex.x>=0&&nex.x<n&&nex.y>=0&&nex.y<m&&vis[nex.x][nex.y]==0&&a[nex.x][nex.y]!='#')
{
s.push(nex);
output[nex.x][nex.y]=output[now.x][now.y]+1;
vis[nex.x][nex.y]=1;
}
}
}
return -1;
}
void dfs(int i,int j,int d) //左转深搜
{
step++;
if(i==ex&&j==ey)return ;
if(d==0)
{
if(mark[i][j-1])dfs(i,j-1,1);
else if(mark[i-1][j])dfs(i-1,j,0);
else if(mark[i][j+1])dfs(i,j+1,3);
else dfs(i+1,j,2);
}
if(d==1)
{
if(mark[i+1][j])dfs(i+1,j,2);
else if(mark[i][j-1])dfs(i,j-1,1);
else if(mark[i-1][j])dfs(i-1,j,0);
else dfs(i,j+1,3);
}
if(d==2)
{
if(mark[i][j+1])dfs(i,j+1,3);
else if(mark[i+1][j])dfs(i+1,j,2);
else if(mark[i][j-1])dfs(i,j-1,1);
else dfs(i-1,j,0);
}
if(d==3)
{
if(mark[i-1][j])dfs(i-1,j,0);
else if(mark[i][j+1])dfs(i,j+1,3);
else if(mark[i+1][j])dfs(i+1,j,2);
else dfs(i,j-1,1);
}
}
void dfs2(int i,int j,int d) //右转深搜
{
step2++;
if(i==ex&&j==ey)return ;
if(d==0)
{
if(mark[i][j+1])dfs2(i,j+1,3);
else if(mark[i-1][j])dfs2(i-1,j,0);
else if(mark[i][j-1])dfs2(i,j-1,1);
else dfs2(i+1,j,2);
}
if(d==1)
{
if(mark[i-1][j])dfs2(i-1,j,0);
else if(mark[i][j-1])dfs2(i,j-1,1);
else if(mark[i+1][j])dfs2(i+1,j,2);
else dfs2(i,j+1,3);
}
if(d==2)
{
if(mark[i][j-1])dfs2(i,j-1,1);
else if(mark[i+1][j])dfs2(i+1,j,2);
else if(mark[i][j+1])dfs2(i,j+1,3);
else dfs2(i-1,j,0);
}
if(d==3)
{
if(mark[i+1][j])dfs2(i+1,j,2);
else if(mark[i][j+1])dfs2(i,j+1,3);
else if(mark[i-1][j])dfs2(i-1,j,0);
else dfs2(i,j-1,1);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(mark,0,sizeof(mark));
int dfscur;
scanf("%d%d",&m,&n);
for(int i=0;i<n;i++)
{
scanf("%s",a[i]);
for(int j=0;j<m;j++)
{
if(a[i][j]=='.')
{
mark[i][j]=1;
}
if(a[i][j]=='S')
{
x=i;
y=j;
if(i==n-1)
dfscur=0;
else if(j==m-1)
dfscur=1;
else if(i==0)
dfscur=2;
else if(j==0)
dfscur=3;
}
if(a[i][j]=='E')
{
mark[i][j]=1;
ex=i;
ey=j;
}
}
}
step=1,step2=1;
switch(dfscur) //左优先深搜
{
case 0:dfs(x-1,y,0);break;
case 1:dfs(x,y-1,1);break;
case 2:dfs(x+1,y,2);break;
case 3:dfs(x,y+1,3);break;
}
printf("%d ",step); //右优先深搜
switch(dfscur)
{
case 0:dfs2(x-1,y,0);break;
case 1:dfs2(x,y-1,1);break;
case 2:dfs2(x+1,y,2);break;
case 3:dfs2(x,y+1,3);break;
}
printf("%d ",step2);
printf("%d\n",bfs(x,y)); //最短路广搜
}
}