USACO 2.3.1 跨越栅栏

来源:互联网 发布:网络执法官破解版 编辑:程序博客网 时间:2024/05/29 04:45
USACO 2.3.1 跨越栅栏
by MPS
====================================================================================
在此,感谢@NOIRP大牛的思路提醒,给了我出发点,使我最终解决了这题。
====================================================================================
【题目描述】

农夫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