【刷题】洛谷 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

 

posted @ 2017-06-14 18:08  HYJ_cnyali  阅读(288)  评论(0编辑  收藏  举报