您的位置:首页 > Web前端

[USACO2.4]穿越栅栏 Overfencing

2017-07-28 12:46 447 查看


题目描述

描述 农夫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个字符表示迷宫

输出格式:

输出一个单独的整数,表示能保证牛从迷宫中任意一点走出迷宫的最小步数。


输入输出样例

输入样例#1:
5 3
+-+-+-+-+-+
|         |
+-+ +-+ + +
|     | | |
+ +-+-+ + +
| |     |
+-+ +-+-+-+


输出样例#1:
9

4000


说明

翻译来自NOCOW

USACO 2.4

【题解】

通常的,最短路用广度优先搜索

/*
ID:luojiny1
LANG:C++
TASK:maze1
*/
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=100*2+100,maxm=38*2+100;
bool up[maxn][maxm]={0},down[maxn][maxm]={0},left[maxn][maxm]={0},right[maxn][maxm]={0},done[maxn][maxm];
int m,n,d[maxn][maxm],ans=0;
char str[maxn][maxm];
bool ok(char ch)
{
return ch=='+'||ch=='-'||ch=='|';
}
struct Node{
int i,j,step;
};
void bfs(int i,int j){
queue<Node>Q;
Q.push((Node){i,j,1});
while(!Q.empty())
{
Node u=Q.front();Q.pop();
if(done[u.i][u.j])continue;
done[u.i][u.j]=true;
if(d[u.i][u.j]>u.step)d[u.i][u.j]=u.step;
if(up[u.i][u.j]==0&&u.i-1>=0)Q.push((Node){u.i-1,u.j,u.step+1});
if(right[u.i][u.j]==0&&u.j+1<m)Q.push((Node){u.i,u.j+1,u.step+1});
if(down[u.i][u.j]==0&&u.i+1<n)Q.push((Node){u.i+1,u.j,u.step+1});
if(left[u.i][u.j]==0&&u.j-1>=0)Q.push((Node){u.i,u.j-1,u.step+1});
}

}

int main()
{
freopen("maze1.in","r",stdin);
freopen("maze1.out","w",stdout);
memset(d,0x7f,sizeof(d));
scanf("%d%d\n",&m,&n);
for(int i=0;i<2*n+1;i++){
for(int j=0;j<2*m+1;j++){
char ch=getchar();
str[i][j]=ch;
} getchar();}
for(int i=1;i<=n*2-1;i+=2)
for(int j=1;j<=m*2-1;j+=2){
if(ok(str[i-1][j]))up[i/2][j/2]=1;
if(ok(str[i][j+1]))right[i/2][j/2]=1;
if(ok(str[i+1][j]))down[i/2][j/2]=1;
if(ok(str[i][j-1]))left[i/2][j/2]=1;
}
for(int i=0;i<m;i++)
if(up[0][i]==0){
memset(done,0,sizeof(done));
bfs(0,i);
}
for(int i=0;i<n;i++){
if(left[i][0]==0){
memset(done,0,sizeof(done));
bfs(i,0);
}
if(right[i][m-1]==0){
memset(done,0,sizeof(done));
bfs(i,m-1);
}
}
for(int i=0;i<m;i++)
if(down[n-1][i]==0){
memset(done,0,sizeof(done));
bfs(n-1,i);
}
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)if(d[i][j]>ans)ans=d[i][j];
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: