【USACO2.4.2】穿越栅栏
2016-07-15 14:31
260 查看
【问题描述】
FJ搭建了一个巨大的用栅栏围成的迷宫。幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口,并且从迷宫中的任意一点都能找到一条走出迷宫的路。给定迷宫的宽 W 及长 H 和这个迷宫,然后计算从迷宫中最“糟糕”的那一个点走出迷宫所需的最少步数。
【输入格式】
第一行: W和H(用空格隔开)
第二行至第2*H+1行: 每行2*W+1个字符表示迷宫
【输出格式】
输出一个单独的整数,表示能保证牛从迷宫中任意一点走出迷宫的最小步数。
【输入样例】
【输出样例】
算法:棋盘上的BFS(多源)
这个题输入有点恶心,给的不是一个正正规规的迷宫问题的迷宫而给的是迷宫的形状图,所以需要转化,把输入矩阵首行首列的坐标标号为0,那些横纵坐标为基数且自身为空格的点就是一个标准棋盘上的格子。
由于是墙障碍,设三元组a[x][y][4] 在=1时表示棋盘上点(x,y)的某个方向上有一堵墙。
又人为规定:
0: 西1: 北2: 东3: 南
再对原矩阵进行扫描标记,转化为普通的墙障碍问题,见【USACO2.4.2简单版本】
但要注意的是,由于没有给出具体的出口坐标,所以要用循环查找,但要注意特殊的点(四个角上的点不管一面无墙还是两面无墙都只存一次)
贴上代码
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++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C++的template模板中class与typename关键字的区别分析
- C与C++之间相互调用实例方法讲解