USACO 2.3.1 跨越栅栏
来源:互联网 发布:网络执法官破解版 编辑:程序博客网 时间:2024/05/29 04:45
USACO 2.3.1 跨越栅栏
by MPS
====================================================================================
在此,感谢@NOIRP大牛的思路提醒,给了我出发点,使我最终解决了这题。
====================================================================================
【题目描述】
给定迷宫的宽W(1<=W<=38)及长H(1<=H<=100)。
2*H+1行,每行2*W+1的字符以下面给出的格式表示一个迷宫。然后计算从迷宫中最“糟糕”的那一个点走出迷宫所需的步数。(即使从这一点以最优的方式走向最靠近的出口,它仍然需要最多的步数)当然了,牛们只会水平或垂直地在X或Y轴上移动,他们从来不走对角线。每移动到一个新的方格算作一步(包括移出迷宫的那一步)
这是一个W=5,H=3的迷宫:
如上图的例子,栅栏的柱子只出现在奇数行或奇数列。每个迷宫只有两个出口。
农夫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*M+1个字符,构成这个迷宫
【样例输入】 【样例输出】
5 3 9((6,2)为最糟糕点)【样例输入】 【样例输出】
+-+-+-+-+-+
| |
+-+ +-+ + +
| | | |
+ +-+-+ + +
| | |
+-+ +-+-+-+
【分析】
也许是我太渣渣了,一开始居然想枚举每一个点,然后跑一遍BFS,结果TLE了7个点...然后拿去问@NOIRP,他看了一下,就机智地说反向BFS,我想了一下,就知道应该以两个出口分别为起点,跑一遍BFS,然后就AC了,注意这题有几个坑:
(1)每次前进2格,为什么这么说呢?比如说上图:不能走有+号的一行,因为那行实际不存在(想一想,为什么?)
(2)是2*...不要数组开小了....
(3)不能直接以起点BFS,因为要考虑到第(1)个坑,每次走到偶数格,所以要特殊处理起点,如果起点是(2,1)则应改为(2,2)(想一想,为什么?),其余以此类推
想清楚这几点以后,基本上就能AC了
【代码】
#include <iostream>#include <cstdio>#include <algorithm>#include <cctype>#include <cstring>#include <string>#include <cstdlib>#include <vector>#include <queue>#include <deque>using namespace std;const int MaxN=203;struct xOy{int x,y;};int vis[MaxN][MaxN];char maze[MaxN][MaxN];int n,m,ans;int out1x,out2x,out1y,out2y;void readfile(){int i,j;char c;scanf("%d%d",&m,&n);m=m*2+1;n=n*2+1;for(i=1;i<=n;i++) for(j=1;j<=m;j++){ scanf("%c",&c);if(c=='\n')scanf("%c",&c);maze[i][j]=c; if((j==m || j==1 || i==n || i==1)&& maze[i][j]==' ' && out1x==0 && out1y==0)out1x=i,out1y=j; if((i==n || i==1 || j==1 || j==m)&& maze[i][j]==' ')out2x=i,out2y=j; }}queue<xOy> q;void bfs(int x,int y){vis[x][y]=0;if(y==m)y--;if(y==1)y++;if(x==n)x--;if(x==1)x++;vis[x][y]=1; q.push((struct xOy){x,y}); int headx,heady;while(!q.empty()){ headx=q.front().x; heady=q.front().y; q.pop();//拓展四个方向↓ if((headx+2<=n) && maze[headx+1][heady]==' ' && vis[headx+2][heady]>vis[headx][heady]+1){q.push((struct xOy){headx+2,heady});vis[headx+2][heady]=vis[headx][heady]+1;} if((headx-2>0) && maze[headx-1][heady]==' ' && vis[headx-2][heady]>vis[headx][heady]+1){q.push((struct xOy){headx-2,heady});vis[headx-2][heady]=vis[headx][heady]+1;} if((heady+2<=m) && maze[headx][heady+1]==' ' && vis[headx][heady+2]>vis[headx][heady]+1){q.push((struct xOy){headx,heady+2});vis[headx][heady+2]=vis[headx][heady]+1;} if((heady-2>0) && maze[headx][heady-1]==' ' && vis[headx][heady-2]>vis[headx][heady]+1){q.push((struct xOy){headx,heady-2});vis[headx][heady-2]=vis[headx][heady]+1;}}}void solve(){int i,j,ans=0;memset(vis,0x7F,sizeof(vis));bfs(out1x,out1y);bfs(out2x,out2y);for(i=2;i<=n;i+=2)//只能走偶数格,不然的话会出现结果=0x7F for(j=2;j<=m;j+=2) if(maze[i][j]==' ' && vis[i][j]>ans)ans=vis[i][j];printf("%d",ans);}int main(){ freopen("maze1.in","r",stdin); freopen("maze1.out","w",stdout); readfile(); solve(); return 0;}
0 0
- USACO 2.3.1 跨越栅栏
- USACO 3.3.1 骑马修栅栏
- USACO Overfencing 穿越栅栏
- 【USACO题库】3.4.1 Closed Fences闭合的栅栏
- 【USACO题库】3.3.1 Riding the Fences骑马修栅栏
- usaco 3.3 骑马修栅栏
- USACO 2.4.2 穿越栅栏
- USACO Training 3.4.1 Closed Fences闭合的栅栏 题解与分析
- JZOJ1288.【USACO题库】3.3.1 Riding the Fences骑马修栅栏
- 【USACO题库】2.4.2 Overfencing穿越栅栏
- USACO 3.3 骑马修栅栏
- 栅栏
- usaco 4.1.2 Fence Rails栅栏的木料
- bzoj 1600 & Usaco 月赛 2008 建造栅栏 题解
- 【USACO题库】2.4.2 Overfencing穿越栅栏(搜索)
- USACO 2.4.2改 穿越栅栏(多源bfs)
- USACO 2.4.2 穿越栅栏(原题) 解题报告
- 2039 骑马修栅栏 USACO[图论—欧拉路]
- View和 Viewgroup之间的区别
- Linux 链接脚本详解
- 菜鸟程序猿初识常见CPU架构
- nginx upstream的分配方式。
- Ubuntu中dpkg方式安装软件包
- USACO 2.3.1 跨越栅栏
- 算法与数据结构基础4:C++二叉树实现及遍历方法大全
- 【android】HandlerThread的使用及源码剖析
- 基于ATL的控件中使用加速键(AtlLoadAccelerators)
- MBA写作串讲笔记 1
- poj1482(隐式图求最短路)
- 孟岩——什么是高级C++,软件工业化时代的C++价值观
- 【java】创建线程的三种方式浅析
- Unity3D学习基本知识,继承