zoukankan      html  css  js  c++  java
  • luogu P1519 穿越栅栏 Overfencing

    题目描述

    描述 农夫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 * W + 1个字符表示迷宫

     

    输出格式:

     

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

    输入输出样例

    输入样例#1: 
    5 3
    +-+-+-+-+-+
    |         |
    +-+ +-+ + +
    |     | | |
    + +-+-+ + +
    | |     |  
    +-+ +-+-+-+
    输出样例#1: 
    9
    

    说明

    翻译来自NOCOW

    USACO 2.4

    刚读完题,感觉挺简单啊,不过研究了一下样例,一脸懵逼,这咋可能?。

    经过机房某位 S型 dalao(son)的解读,哦,so ga si nei,吆西吆西,interisting!!!

    再次就借花献佛了。

    关于的理解题意:

    为了便于理解,这里稍微修改一下题目。

    奇数行的栅栏(就是由‘+’和‘-’号组成)将其看做一层类似膜结构,一层防护膜(没有厚度),穿越不占距离。

    然后看偶数列,这里需要将偶数列和其两侧的‘-’看做一个整体,亦可以理解为忽略偶数列,只考虑奇数列。

    这里拿样例图解:

    结合上图,对题意理解就没什么问题了。

    解题剖析:

    1.读入含空格矩阵:

    想了半天,试了多种输入方法,最终貌似只有getline(:不会用戳我啊)可以用。

    但是在输入时,需要多输入一行,并且第一行和第二行会重复,其他没毛病,最后貌似没啥大碍。

        scanf("%d%d",&w,&h);
        w=w*2+1;h=h*2+1;
        for(int i=1;i<=h+1;i++)getline(cin,a[i]);

    读入是这样的,若有某位dalao明白以上出现的情况,希望讨论区不吝赐教。

    2.字符矩阵转换数字矩阵

    在这里定义一个int型map数组。

    map[i][j]表示走到这个点需要消耗的距离(偶数行为0,奇数行有空地的话消耗为1)

    在字符矩阵中[i][j]这个点为栅栏,不能走,将map[i][j]定义为2.

    注意前边说到,输入字符时会有一行多余,所以在转换时处理一下。

    此部分代码为:

        for(int i=2;i<=h+1;i++)
            for(int j=0;j<w;j++)
            {
                
                if(a[i][j]==32)
                {
                    if((i-1)%2==1)map[i-1][j+1]=0;
                    else if((j+1)%2==0)map[i-1][j+1]=1;
                    else map[i-1][j+1]=0;
                }
                else map[i-1][j+1]=2;
            }

    3.初始化:

    ans[i][j]数组记录走到 i,j这个点到出口的最近距离,栅栏处直接定义为-1。

    void initial()
    {
        for(int i=1;i<=h;i++)
            for(int j=1;j<=w;j++)
                if(map[i][j]==2)ans[i][j]=-1;
                else ans[i][j]=214748364;
    }

    4.找出出口:

    这没啥好说的,四个边找出口(注意经以上过程出口可能为0,可能为1)。

        for(int i=1;i<=w;i++)if(map[1][i]==0||map[1][i]==1)bfs(1,i);
        for(int i=1;i<=w;i++)if(map[h][i]==0||map[h][i]==1)bfs(h,i);
        for(int i=1;i<=h;i++)if(map[i][1]==0||map[i][1]==1)bfs(i,1);
        for(int i=1;i<=h;i++)if(map[i][w]==0||map[i][w]==1)bfs(i,w);

    5.大搜索

    已经处理处每一格的消耗距离,在搜索时,加上就好啦。

    两个出口,需要搜索两边所以搜完注意初始化,bool型数组。

    bool vis[N][M];
    struct ahah{
        int x,y;
    }str,cur;
    queue <ahah> que;
    void bfs(int x,int y)
    {
        ans[x][y]=0;
        vis[x][y]=1;
        str.x=x;str.y=y;
        que.push(str);
        while(!que.empty())
        {
            cur=que.front();
            que.pop() ;
            for(int i=0;i<4;i++)
            {
                str.x=cur.x+dx[i];
                str.y=cur.y+dy[i];
                if(map[str.x][str.y]!=2&&str.x>=1&&str.x<=h
                &&str.y>=1&&str.y<=w&&!vis[str.x][str.y])
                {
                    ans[str.x][str.y]=min(ans[cur.x][cur.y]+map[str.x][str.y],ans[str.x][str.y]);
                                
                    vis[str.x][str.y]=1;
                    que.push(str); 
                }
            }
        } 
        memset(vis,0,sizeof(vis));
    }

    6.找出最大值

    将ans数组循环一遍,找出最大值,输出即可。

    完整代码:

    /*.........................
    作者:Manjusaka
    时间:2018/7/11
    题目:P1519 Overfencing
    ..........................*/
    
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <queue> 
    using namespace std;
    #define N int(100)
    #define M int(210)
    int dx[5]={0,0,1,-1},dy[5]={1,-1,0,0};
    string a[N];
    int w,h,MAX;
    int x[4],y[4],k;
    int map[N][M];
    int ans[N][M];
    void check();
    void _scanf();
    void initial();
    void bfs(int ,int );
    void _scanf()
    {
        scanf("%d%d",&w,&h);
        w=w*2+1;h=h*2+1;
        for(int i=1;i<=h+1;i++)getline(cin,a[i]);
        for(int i=2;i<=h+1;i++)
            for(int j=0;j<w;j++)
            {
                
                if(a[i][j]==32)
                {
                    if((i-1)%2==1)map[i-1][j+1]=0;
                    else if((j+1)%2==0)map[i-1][j+1]=1;
                    else map[i-1][j+1]=0;
                }
                else map[i-1][j+1]=2;
            }
    //    cout<<"
    ";for(int i=1;i<=h;i++){for(int j=1;j<=w;j++){cout<<map[i][j];}cout<<endl;}
        check();
    }
    void check()
    {
        initial();    
        for(int i=1;i<=w;i++)if(map[1][i]==0||map[1][i]==1)bfs(1,i);
        for(int i=1;i<=w;i++)if(map[h][i]==0||map[h][i]==1)bfs(h,i);
        for(int i=1;i<=h;i++)if(map[i][1]==0||map[i][1]==1)bfs(i,1);
        for(int i=1;i<=h;i++)if(map[i][w]==0||map[i][w]==1)bfs(i,w);
        for(int i=1;i<=h;i++)
        {
            cout<<"
    ";
            for(int j=1;j<=w;j++)
            {
                printf("%3d",ans[i][j]);
            }
        }
    }
    void initial()
    {
        for(int i=1;i<=h;i++)
            for(int j=1;j<=w;j++)
                if(map[i][j]==2)ans[i][j]=-1;
                else ans[i][j]=214748364;
    }
    bool vis[N][M];
    struct ahah{
        int x,y;
    }str,cur;
    queue <ahah> que;
    void bfs(int x,int y)
    {
        ans[x][y]=0;
        vis[x][y]=1;
        str.x=x;str.y=y;
        que.push(str);
        while(!que.empty())
        {
            cur=que.front();
            que.pop() ;
            for(int i=0;i<4;i++)
            {
                str.x=cur.x+dx[i];
                str.y=cur.y+dy[i];
                if(map[str.x][str.y]!=2&&str.x>=1&&str.x<=h
                &&str.y>=1&&str.y<=w&&!vis[str.x][str.y])
                {
                    ans[str.x][str.y]=min(ans[cur.x][cur.y]+map[str.x][str.y],ans[str.x][str.y]);
                                
                    vis[str.x][str.y]=1;
                    que.push(str); 
                }
            }
        } 
        memset(vis,0,sizeof(vis));
    }
    void _printf()
    {
        for(int i=1;i<=h;i++)
            for(int j=1;j<=w;j++)
                MAX=max(MAX,ans[i][j]);
        printf("
    %d",MAX);
    }
    int main()
    {
        _scanf();
        _printf();
    }

    求助大佬!!:

    按题目要求来说二位数组开到100*200应该完全可以啊,为什么会比RE,求解释。

  • 相关阅读:
    ActiveSync合作关系对话框的配置
    WINCE对象存储区(object store)
    Wince 隐藏TASKBAR的方法
    Wince输入法换肤换语言机制
    poj 3080 Blue Jeans 解题报告
    codeforces A. Vasily the Bear and Triangle 解题报告
    hdu 1050 Moving Tables 解题报告
    hdu 1113 Word Amalgamation 解题报告
    codeforces A. IQ Test 解题报告
    poj 1007 DNA Sorting 解题报告
  • 原文地址:https://www.cnblogs.com/rmy020718/p/9297006.html
Copyright © 2011-2022 走看看