【问题描述】
FJ搭建了一个巨大的用栅栏围成的迷宫。幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口,并且从迷宫中的任意一点都能找到一条走出迷宫的路。给定迷宫的行和列数和这个迷宫,然后计算从迷宫中最“糟糕”的那一个点走出迷宫所需的最少步数。
【输入格式】
第一行为正数m和n,表示迷宫的行数和列数,用空格隔开。迷宫用一个由数字组成的矩阵表示,一个数字表示迷宫的一个格子。每一个格子的数字告诉我们这个格子的东、西、南、北是否有栅栏存在。每个数字是由以下四个整数的某个或某几个或一个都没有加起来的。
1: 在西面有栅栏
2: 在北面有栅栏
4: 在东面有栅栏
8: 在南面有墙
迷宫内部的栅栏会被规定两次。比如说(1,1)南面的栅栏,亦会被标记为(2,1)北面的栅栏。
【输出格式】
输出一个单独的整数,表示能保证牛从迷宫中任意一点走出迷宫的最小步数。
【输入样例】
3 5
11 2 10 2 6
3 8 14 5 5
13 3 10 12 9
【输出样例】
9
【样例解释】
样例输入的迷宫如图a,最糟糕的点是左下角的格子,走出迷宫需要9步,见图b。
【数据范围】
1 <= m <= 38
1 <= n <= 100
【来源】
根据P1236改编
这是一道带墙的棋盘问题,直接标记可以走的方向就可以了。而多个起点,直接多元bfs就可以了。详见(http://blog.csdn.net/qq_35546274/article/details/51896423)。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=105;
struct shu
{
int u,v;
};
int a[maxn][maxn][4];//0东,1南,2西,3北。
int n,m,x1,y1,x2,y2,vis[maxn][maxn],d[maxn][maxn];
int dx[]={0,1,0,-1};
int dy[]={1,0,-1,0};
void init()
{
memset(a,0,sizeof(a));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
int x;
scanf("%d",&x);
if(x>=8)
{
a[i][j][1]=1;
x-=8;
}
if(x>=4)
{
a[i][j][0]=1;
x-=4;
}
if(x>=2)
{
a[i][j][3]=1;
x-=2;
}
if(x>=1)
{
a[i][j][2]=1;
x-=1;
}
}
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
}
void bfs()
{
queue<shu>q;
q.push((shu){x1,y1});
q.push((shu){x2,y2});
d[x1][y1]=1;
vis[x1][y1]=1;
d[x2][y2]=1;
vis[x2][y2]=1;
while(!q.empty())
{
shu t=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int nx=t.u+dx[i],ny=t.v+dy[i];
if(a[t.u][t.v][i]) continue;
if(nx<1||ny<1||nx>n||ny>m) continue;
if(vis[nx][ny]) continue;
vis[nx][ny]=1;
d[nx][ny]=d[t.u][t.v]+1;
q.push((shu){nx,ny});
}
}
}
int main()
{
freopen("pass.in","r",stdin);
//freopen("pass.out","w",stdout);
init();
int ans=0;
memset(vis,0,sizeof(vis));
memset(d,0,sizeof(d));
bfs();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
ans=max(ans,d[i][j]);
printf("%d",ans);
return 0;
}