【刷题】洛谷 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个字符表示迷宫
输出格式:
输出一个单独的整数,表示能保证牛从迷宫中任意一点走出迷宫的最小步数。
输入输出样例
5 3 +-+-+-+-+-+ | | +-+ +-+ + + | | | | + +-+-+ + + | | | +-+ +-+-+-+
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 }