zoukankan      html  css  js  c++  java
  • 【刷题】洛谷 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

    题解

    这道题搜索可过,不过大都每个点都搜,这种朴素算法需要记忆化,不如换了一种方式,从出口开始搜,只要一个格子上下左右可以走,那么就将走到的格子原来的步数(初始化全部赋值为无穷大)与出发的格子的步数加1做比较,如果出发的格子的步数加1更小,那么继续搜,否则就不管了(这是显然的)。

    然而麻烦的是输入。。。太恶心了!最后用结构体记录的,存下一个格子东南西北(上下左右)能否到达,这样对于后面的算法来说操作更简单。

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<cmath>
      5 using namespace std;
      6 const int MAXN=100+5,inf=1000000000;
      7 int w,h,f[MAXN][MAXN],ans=1;
      8 struct node{
      9     bool north;
     10     bool south;
     11     bool east;
     12     bool west;
     13     node(){
     14         north=false;
     15         south=false;
     16         east=false;
     17         west=false;
     18     }
     19 };
     20 node room[MAXN][MAXN];
     21 inline void read(int &x)
     22 {
     23     x=0;
     24     char c=getchar();
     25     while(c<'0'||c>'9')c=getchar();
     26     while(c>='0'&&c<='9')
     27     {
     28         x=x*10+c-'0';
     29         c=getchar();
     30     }
     31 }
     32 inline void init()
     33 {
     34     for(register int i=1;i<=h;++i)
     35     {
     36         for(register int j=1;j<=w;++j)f[i][j]=inf;
     37     }
     38 }
     39 inline bool judge(int x,int y)
     40 {
     41     if(x<1||x>h||y<1||y>w)return false;
     42     return true;
     43 }
     44 inline void search(int x,int y)
     45 {
     46     if(room[x][y].north)
     47     {
     48         int dx=x-1,dy=y;
     49         if(judge(dx,dy)&&(f[x][y]+1<f[dx][dy]))
     50         {
     51             f[dx][dy]=f[x][y]+1;
     52             search(dx,dy);
     53         }
     54     }
     55     if(room[x][y].south)
     56     {
     57         int dx=x+1,dy=y;
     58         if(judge(dx,dy)&&(f[x][y]+1<f[dx][dy]))
     59         {
     60             f[dx][dy]=f[x][y]+1;
     61             search(dx,dy);
     62         }
     63     }
     64     if(room[x][y].east)
     65     {
     66         int dx=x,dy=y+1;
     67         if(judge(dx,dy)&&(f[x][y]+1<f[dx][dy]))
     68         {
     69             f[dx][dy]=f[x][y]+1;
     70             search(dx,dy);
     71         }
     72     }
     73     if(room[x][y].west)
     74     {
     75         int dx=x,dy=y-1;
     76         if(judge(dx,dy)&&(f[x][y]+1<f[dx][dy]))
     77         {
     78             f[dx][dy]=f[x][y]+1;
     79             search(dx,dy);
     80         }
     81     }
     82 }
     83 int main()
     84 {
     85     scanf("%d%d",&w,&h);
     86     getchar();getchar();
     87     char c;
     88     for(register int i=1;i<=2*h+1;++i)
     89     {
     90         for(register int j=1;j<=2*w+1;++j)
     91         {
     92             scanf("%c",&c);
     93             if(i%2!=0)
     94             {
     95                 if(c==' ')
     96                 {
     97                     int a=(i+1)/2,b=j/2;
     98                     room[a][b].north=true;
     99                     room[a-1][b].south=true;
    100                 }
    101             }
    102             else
    103             {
    104                 if(j%2!=0)
    105                 {
    106                     if(c==' ')
    107                     {
    108                         int a=i/2,b=(j+1)/2;
    109                         room[a][b].west=true;
    110                         room[a][b-1].east=true;
    111                     }
    112                 }
    113             }
    114         }
    115         getchar();getchar();
    116     }
    117     init();
    118     for(register int i=1;i<=w;++i)if(room[1][i].north)
    119     {
    120         f[1][i]=1;
    121         search(1,i);
    122     }
    123     for(register int i=1;i<=w;++i)if(room[h][i].south)
    124     {
    125         f[h][i]=1;
    126         search(h,i);
    127     }
    128     for(register int i=1;i<=h;++i)if(room[i][1].west)
    129     {
    130         f[i][1]=1;
    131         search(i,1);
    132     }
    133     for(register int i=1;i<=h;++i)if(room[i][w].east)
    134     {
    135         f[i][w]=1;
    136         search(i,w);
    137     }
    138     for(register int i=1;i<=h;++i)
    139     {
    140         for(register int j=1;j<=w;++j)ans=max(ans,f[i][j]);
    141     }
    142     cout<<ans;
    143     return 0;
    144 }
    P1519 穿越栅栏 Overfencing
  • 相关阅读:
    四则运算2实验及表格
    四则运算2初步构思
    2015.3.6的程序实践
    对《梦断代码》的阅读计划
    林锐——软件思想阅读笔记2
    二维数组最大子数组溢出问题
    循环数组求最大子数组
    电梯调度需求分析调研报告
    二维数组求最大子数组
    四则运算实现用户输入答案并统计正确数量
  • 原文地址:https://www.cnblogs.com/hongyj/p/7010247.html
Copyright © 2011-2022 走看看