• USACO / Overfencing(BFS)


    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;
    }
  • 相关阅读:
    SQL Server 存储过程
    String.format Tutorial
    第五次
    第四次
    第三次
    第一次作业
    第二次
    c/c++
    HelloWorld出现的问题
    Android系统架构
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/2598280.html
Copyright © 2020-2023  润新知