您的位置:首页 > 编程语言 > C语言/C++

【USACO2.4.2】穿越栅栏

2016-07-15 14:31 260 查看
【问题描述】

  FJ搭建了一个巨大的用栅栏围成的迷宫。幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口,并且从迷宫中的任意一点都能找到一条走出迷宫的路。给定迷宫的宽 W 及长 H 和这个迷宫,然后计算从迷宫中最“糟糕”的那一个点走出迷宫所需的最少步数。

【输入格式】

第一行: W和H(用空格隔开)

第二行至第2*H+1行: 每行2*W+1个字符表示迷宫

【输出格式】

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

【输入样例】

5 3
+-+-+-+-+-+
|         |
+-+ +-+ + +
|     | | |
+ +-+-+ + +
| |     |
+-+ +-+-+-+


【输出样例】

9


算法:棋盘上的BFS(多源)

这个题输入有点恶心,给的不是一个正正规规的迷宫问题的迷宫而给的是迷宫的形状图,所以需要转化,把输入矩阵首行首列的坐标标号为0,那些横纵坐标为基数且自身为空格的点就是一个标准棋盘上的格子。



由于是墙障碍,设三元组a[x][y][4] 在=1时表示棋盘上点(x,y)的某个方向上有一堵墙。

又人为规定:

0: 西1: 北2: 东3: 南

再对原矩阵进行扫描标记,转化为普通的墙障碍问题,见【USACO2.4.2简单版本】

但要注意的是,由于没有给出具体的出口坐标,所以要用循环查找,但要注意特殊的点(四个角上的点不管一面无墙还是两面无墙都只存一次)

贴上代码

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxn 105
using namespace std;
int W,H;
struct node
{
int x,y;
};
int dx[]={0,-1,0,1};
int dy[]={-1,0,1,0};
char mat[2*maxn][2*maxn];
int a[maxn][maxn][4],vis[maxn][maxn],dist[maxn][maxn];
vector<node>ep;
void BFS()
{
queue<node>q;
for(int k=0;k<ep.size();k++)
{
q.push(ep[k]);
vis[ep[k].x][ep[k].y]=1;
}

while(!q.empty())
{
node i=q.front();q.pop();
for(int k=0;k<4;k++)
{
int nx=i.x+dx[k];
int ny=i.y+dy[k];
if(nx<1 || nx>H || ny<1 || ny>W)continue;
if(vis[nx][ny])continue;
if(a[i.x][i.y][k])continue;
vis[nx][ny]=1;
dist[nx][ny]=dist[i.x][i.y]+1;
q.push((node){nx,ny});
}
}
}

int main()
{
//freopen("my.in","r",stdin);
//freopen("my.out","w",stdout);

scanf("%d%d",&W,&H);
getchar();
for(int i=0;i<=2*H;i++)
gets(mat[i]);

/*for(int i=0;i<=2*H;i++)
printf("%s\n",mat[i]);*/

for(int i=0;i<=2*H;i++)
for(int j=0;j<=2*W;j++)
{
if(mat[i][j]==' ' && i%2==1 && j%2==1)
{
if(j-1>=0 && mat[i][j-1]=='|')a[(i+1)/2][(j+1)/2][0]=1;
if(i-1>=0 && mat[i-1][j]=='-')a[(i+1)/2][(j+1)/2][1]=1;
if(j+1<=2*W && mat[i][j+1]=='|')a[(i+1)/2][(j+1)/2][2]=1;
if(i+1<=2*H && mat[i+1][j]=='-')a[(i+1)/2][(j+1)/2][3]=1;
}
}

for(int j=2;j<W;j++)if(a[1][j][1]==0)ep.push_back((node){1,j});
for(int j=2;j<W;j++)if(a[H][j][3]==0)ep.push_back((node){H,j});
for(int i=2;i<H;i++)if(a[i][1][0]==0)ep.push_back((node){i,1});
for(int i=2;i<H;i++)if(a[i][W][2]==0)ep.push_back((node){i,W});

if(a[1][1][0]==0 || a[1][1][1]==0)ep.push_back((node){1,1});
if(a[1][W][2]==0 || a[1][W][1]==0)ep.push_back((node){1,W});
if(a[H][1][0]==0 || a[H][1][3]==0)ep.push_back((node){H,1});
if(a[H][W][2]==0 || a[H][W][3]==0)ep.push_back((node){H,W});

BFS();

int ans=0;
for(int i=1;i<=H;i++)
for(int j=1;j<=W;j++)
ans=max(ans,dist[i][j]);

printf("%d",ans+1);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c++ USACO 算法竞赛