思路还是比较简单的:只需要求出每个点到出口的最近距离,然后在去其中的最大值作为答案。这个题目麻烦在建图,我建图的时候是将每个点的4个方向的情况都处理出来,然后再进行bfs。其实也可以直接处理出相关点的连通性。然后就是这个题目有两个出口,但是我们只需要将他们一次入队,就可以求出每个点到出口的最近距离了,而不用进行两次bfs(其实也可以加一个源点连接着两个点,可以达到同样的效果)。
代码如下:
/*
ID:15674811
LANG:C++
PROG:maze1
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
struct m
{
int flag[5];
}M[220][110];
typedef struct
{
int x,y,cnt;
}P;
P p1,p2,p3,p4;
queue<P>Q;
int ans,n,m,vis[220][110],d;
bool check1(int x,int y)
{
if(x<0||x>=n||y<0||y>=m)
return false;
if(vis[x][y])
return false;
return true;
}
bool check2(int x,int y)
{
if(x==0||x==2*n)
return true;
if(y==0||y==2*m)
return true;
return false;
}
///上下左右
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
void bfs()
{
while(!Q.empty())
{
p1=Q.front();
Q.pop();
for(int k=0;k<4;k++)
{
int xx=p1.x+dx[k];
int yy=p1.y+dy[k];
if(!check1(xx,yy))
continue;
///这里要特别注意不要写成:M[xx][yy].flag[k]了
if(M[p1.x][p1.y].flag[k]==0)
continue;
vis[xx][yy]=1;
p2.x=xx; p2.y=yy; p2.cnt=p1.cnt+1;
ans=max(ans,p2.cnt);
Q.push(p2);
}
}
}
int main()
{
//freopen("lkl.txt","r",stdin);
freopen("maze1.in","r",stdin);
freopen("maze1.out","w",stdout);
char str[220][110];
while(scanf("%d%d",&m,&n)!=EOF)
{
getchar();
memset(vis,0,sizeof(vis));
memset(M,0,sizeof(M));
for(int i=0;i<2*n+1;i++)
gets(str[i]);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
{
if(str[2*i][2*j+1]==‘ ‘)
{
M[i][j].flag[0]=1;
if(check2(2*i,2*j+1))
{
vis[i][j]=1;
p1.x=i; p1.y=j; p1.cnt=1;
Q.push(p1);
}
}
if(str[2*i+2][2*j+1]==‘ ‘)
{
M[i][j].flag[1]=1;
if(check2(2*i+2,2*j+1))
{
vis[i][j]=1;
p1.x=i; p1.y=j; p1.cnt=1;
Q.push(p1);
}
}
if(str[2*i+1][2*j]==‘ ‘)
{
M[i][j].flag[2]=1;
if(check2(2*i+1,2*j))
{
vis[i][j]=1;
p1.x=i; p1.y=j; p1.cnt=1;
Q.push(p1);
}
}
if(str[2*i+1][2*j+2]==‘ ‘)
{
M[i][j].flag[3]=1;
if(check2(2*i+1,2*j+2))
{
vis[i][j]=1;
p1.x=i; p1.y=j; p1.cnt=1;
Q.push(p1);
}
}
}
ans=1; ///ans要初始化为1而不是0,防止图中只有出口的情况出错
bfs();
printf("%d\n",ans);
}
return 0;
}
时间: 2024-10-11 14:49:56