HDU 1728 逃离迷宫(BFS)
Problem Description
给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?
Input
第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中,
第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。
第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列,y1, y2对应行。
Output
每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。
题目大意:最小转弯问题。(注意哪些是行哪些是列)
思路:一种O(12nm)的算法,用dis[i][x][y]代表上一步走的是i方向,现处于(x, y)所需要的最小转弯数。用两个队列BFS,按转弯数小到大BFS。pre队列记录当前用来拓展的结点,step代表目前的转弯数,同方向的拓展后放到pre队列后面,转弯的拓展后放到cur队列。当pre队列为空之后,交换cur和pre队列,step自增1。若step>k结束循环。
PS:连连看作业的算法有着落啦~~
代码(15MS):
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 8 const int MAXN = 110; 9 10 struct Node { 11 int f, x, y; 12 Node() {} 13 Node(int f, int x, int y): 14 f(f), x(x), y(y) {} 15 }; 16 17 int fx[] = {-1, 0, 1, 0}; 18 int fy[] = {0, 1, 0, -1}; 19 20 int dis[4][MAXN][MAXN]; 21 char mat[MAXN][MAXN]; 22 int T, n, m; 23 int k, x1, y1, x2, y2; 24 25 bool solve() { 26 memset(dis, 0x3f, sizeof(dis)); 27 queue<Node>* pre = new queue<Node>(); 28 queue<Node>* cur = new queue<Node>(); 29 int step = 0; 30 for(int i = 0; i < 4; ++i) pre->push(Node(i, x1, y1)); 31 for(int i = 0; i < 4; ++i) dis[i][x1][y1] = 0; 32 while(step <= k) { 33 Node t = pre->front(); pre->pop(); 34 if(dis[t.f][t.x][t.y] != step) continue; 35 if(t.x == x2 && t.y == y2) return true; 36 for(int i = 0; i < 4; ++i) { 37 if((t.f + 2) % 4 == i) continue; 38 int x = t.x + fx[i], y = t.y + fy[i], d = dis[t.f][t.x][t.y] + (t.f != i); 39 if(mat[x][y] == '.' && d < dis[i][x][y]) { 40 dis[i][x][y] = d; 41 if(t.f == i) pre->push(Node(i, x, y)); 42 else cur->push(Node(i, x, y)); 43 } 44 } 45 if(pre->empty()) { 46 step++; 47 if(cur->empty()) break; 48 swap(pre, cur); 49 } 50 } 51 return false; 52 } 53 54 int main() { 55 scanf("%d", &T); 56 while(T--) { 57 scanf("%d%d", &n, &m); 58 memset(mat, 0, sizeof(mat)); 59 for(int i = 1; i <= n; ++i) scanf("%s", &mat[i][1]); 60 scanf("%d%d%d%d%d", &k, &y1, &x1, &y2, &x2); 61 puts(solve() ? "yes" : "no"); 62 } 63 }