题目描述
描述 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫。幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口。更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意一点找到一条走出迷宫的路。给定迷宫的宽度W(1<=W<=38)及高度H(1<=H<=100)。 2*H+1行,每行2*W+1的字符以下面给出的格式表示一个迷宫。然后计算从迷宫中最“糟糕”的那一个点走出迷宫所需的步数(就是从最“糟糕”的一点,走出迷宫的最少步数)。(即使从这一点以最优的方式走向最靠近的出口,它仍然需要最多的步数)当然了,牛们只会水平或垂直地在X或Y轴上移动,他们从来不走对角线。每移动到一个新的方格算作一步(包括移出迷宫的那一步)这是一个W=5,H=3的迷宫:
+-+-+-+-+-+
| |
+-+ +-+ + +
| | | |
- +-+-+ + +
| | |
+-+ +-+-+-+
(请将上图复制到记事本观看更加)
如上图的例子,栅栏的柱子只出现在奇数行或奇数列。每个迷宫只有两个出口。
输入输出格式
输入格式:第一行: W和H(用空格隔开)
第二行至第2 H + 1行: 每行2 W + 1个字符表示迷宫
输出格式:输出一个单独的整数,表示能保证牛从迷宫中任意一点走出迷宫的最小步数。
输入输出样例
5 3 +-+-+-+-+-+ | | +-+ +-+ + + | | | | + +-+-+ + + | | | +-+ +-+-+-+
9
说明
翻译来自NOCOW
USACO 2.4
此题可以发现出口已被限制为有且仅有两个,因此我们瞬间就可以想到从这两个点开始广搜,更新每个点的最短距离。
但是由于此地图是放大后的,因此每跳过两个格子(字符)才算走了一步
但是:千万注意:格式!若要用gets(),则读完那两个数字后不能用getchar,而要用gets,去掉一个空串,被坑了太久。。。。。。
贴上代码:
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define inf 999999999
#define For(i,a,b) for(i=(a);i<=(b);++i)
#define rep(i,a,b) for(i=(a);i>=(b);--i)
#define mm(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn = 100010;
int vis[1010][1010];
int m,n;
char s[maxn];
int stx1,sty1,stx2,sty2;
int dp[1010][1010];
struct node{
int x,y,t;
};
int p[1010][1010];
int d[4][2]={{2,0},{-2,0},{0,2},{0,-2}};
int mis[4][2] = {{1,0},{-1,0},{0,1},{0,-1}};//要跨两个则中间那个也不能有障碍
int ansmax;
void solve(int tx,int ty,bool type){
int i;
queue<node> q;
node T;
T.x = tx,T.y = ty;
T.t = 0;
q.push(T);
p[tx][ty] = 1;
while(!q.empty()){
T = q.front();
q.pop();
For(i,0,3){
int u = T.x + d[i][0],v = T.y + d[i][1], u2 = T.x + mis[i][0], v2 = T.y + mis[i][1];
if(u<1 || v<1 || u>m*2+1 || v>n*2+1 || !vis[u][v] || !vis[u2][v2] || p[u][v])continue;
p[u][v]=1;
dp[u][v] = min(dp[u][v],T.t + 1);
if(type)ansmax = max(dp[u][v] , ansmax);//第二个出口搜的时候再更新
node h;
h.x = u,h.y = v;h.t = T.t+1;
q.push(h);
}
}
}
int main(){
int i,j;
int cnt = 0;
int ans = 0;
scanf("%d%d",&n,&m);
gets(s);//就是这里
For(i,1,m*2+1){
char c;
ans = 0;
gets(s);
For(j,0,n*2){
if(s[j]==' '){
if(j==0 || i==1 || i==m*2+1 || j==n*2){
++cnt;
if(cnt==1){//这里需要模拟一下
if(j==0)stx1 = i,sty1 = j;
else if(i==1) stx1 = i-1,sty1 = j+1;
else if(i==m*2+1)stx1 = m*2+2,sty1=j+1;
else stx1 = i,sty1 = n*2+2;
}
else{
if(j==0)stx2 = i,sty2 = j;
else if(i==1) stx2 = i-1,sty2 = j+1;
else if(i==m*2+1)stx2 = m*2+2,sty2=j+1;
else stx2 = i,sty2 = n*2+2;
}
}
vis[i][j+1]=1;
}
dp[i][j+1] = inf;//初始化
}
}
solve(stx1,sty1,0);
mm(p,0);
solve(stx2,sty2,1);
printf("%d\n",ansmax);
return 0;
}