USACO / Overfencing(BFS)

大城市里の小女人 提交于 2020-01-31 19:16:19

Overfencing穿越栅栏

Kolstad and Schrijvers

特别鸣谢lyl提供翻译!


描述 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫。幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口。更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意一点找到一条走出迷宫的路。给定迷宫的宽度W(1<=W<=38)及高度H(1<=H<=100)。 2*H+1行,每行2*W+1的字符以下面给出的格式表示一个迷宫。然后计算从迷宫中最“糟糕”的那一个点走出迷宫所需的步数(就是从最“糟糕”的一点,走出迷宫的最少步数)。(即使从这一点以最优的方式走向最靠近的出口,它仍然需要最多的步数)当然了,牛们只会水平或垂直地在X或Y轴上移动,他们从来不走对角线。每移动到一个新的方格算作一步(包括移出迷宫的那一步)这是一个W=5,H=3的迷宫:

+-+-+-+-+-+
|         |
+-+ +-+ + +
|     | | |
+ +-+-+ + +
| |     |  
+-+ +-+-+-+

如上图的例子,栅栏的柱子只出现在奇数行或奇数列。每个迷宫只有两个出口。

格式

PROGRAM NAME: maze1

INPUT FORMAT:

(file maze1.in)

第一行: W和H(用空格隔开) 
第二行至第2 * H + 1行:  每行2 * W + 1个字符表示迷宫 

OUTPUT FORMAT:

(file maze1.out)

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

SAMPLE INPUT

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

SAMPLE OUTPUT

9
分析

我们用一个数组记录每个格子四面连通情况,然后从输入文件中读入每条边(判断),维护这个数组。然后分别从两个出口做Flood fill,记录每个格子的最短距离。所有格子的最短距离的最大值为所求。


可以将整个图用2*w+1,2*h+1的布尔数组表示,门口处记为一步,最后统计所有偶数行列,输出max div 2 源码 --Lsylsy2 16:24 2007年8月2日 (CST)

 


还可以把两个出口分别作为起点,分别将整个地图走两遍,此时求出两次每个点到两个出口的最短距离中短的一个,再找出最短距离最长的一个点。


注意
第一组数据中
+-+
   // 这行是回车,不是空格(本行有3个空格)     另注:这应该就是空格,经检验过。
+-+

小提示:使用广搜实现Flood Fill更快一点 //但是用dfs flood fill也是可以过的 时间也不算慢


补充:可将地图看为一个图,有一个额外的点表示出口,记可以到出口的一个或两个点到出口距离为1,其余的相邻联通点之间距离记为1(用bool数组即可),然后用堆优化的Dijkstra算法,只用一遍,就可求出各点到出口的最短距离,找出其中最长的即可,效率还不错。


华丽分割线

PS: 可以只做一次BFS, 把两个出口同时加入队列。

/*
ID:138_3531
LANG:C++
TASK:maze1
*/


#include <iostream>
#include <iomanip>
#include <fstream>
#include <cmath>
#include <cstring>


using namespace std;


struct Q
{
    int x;
    int y;
}dl[20000];


int n,w,h;
char map[300][100];
int head,tail;
int d[300][100];
int fx[4][2]={{-2,0},{0,2},{2,0},{0,-2}},fy[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
ifstream fin("maze1.in");
ofstream fout("maze1.out");


void input()
{


    fin>>w>>h;
h=2*h+1;
w=2*w+1;
for(int i=1;i<=h;i++)
{
    fin.get();//因为迷宫中有空格' '型字符,所以读入时不能用cin,用cin.get();
for(int j=1;j<=w;j++)
{
map[i][j]=fin.get();
//cin>>map[i][j];
if((i==1)&&(map[i][j]==' ')) {tail++;dl[tail].x=i+1;dl[tail].y=j; d[i+1][j]=1;}
if((i==h)&&(map[i][j]==' ')) {tail++;dl[tail].x=i-1;dl[tail].y=j; d[i-1][j]=1;}
if((j==1)&&(map[i][j]==' ')) {tail++;dl[tail].x=i;dl[tail].y=j+1; d[i][j+1]=1;}
if((j==w)&&(map[i][j]==' ')) {tail++;dl[tail].x=i;dl[tail].y=j-1; d[i][j-1]=1;}
}
}
}


void bfs(int head,int tail)
{
    int x,y;
    int p,q;
    while(head!=tail)
    {
        head++;
        x=dl[head].x;
        y=dl[head].y;
        for(int i=0;i<=3;i++)
{
p=x+fx[i][0];q=y+fx[i][1];
if((p>0)&&(p<h)&&(q>0)&&(q<w)&&(map[x+fy[i][0]][y+fy[i][1]]==' '))
                       if(d[p][q]==0)
                {
                   tail++;
                    dl[tail].x=p;
                    dl[tail].y=q;
                    d[p][q]=d[x][y]+1;
                }
}
    }
    int total=0;
    for(int i=1;i<=h;i++)
for(int j=1;j<=w;j++)
total=(d[i][j]>total?d[i][j]:total);
fout<<total<<endl;
}


int main()
{
    input();
    bfs(head,tail);
    return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!