UVa1601 The Morning after Halloween (双向广度优先搜索)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa1601 The Morning after Halloween (双向广度优先搜索)相关的知识,希望对你有一定的参考价值。

链接:http://acm.hust.edu.cn/vjudge/problem/51163
分析:已知起点和终点可以利用双向广度优先搜索,正向扩展一层,反向扩展一层,为防止退化,优先扩展结点数多的方向。因为障碍物很多防止TLE,可以先把图除了‘#’抠下来,用cnt给位置编号,x[cnt],y[cnt]为编号为cnt的格子的横纵坐标,id记录坐标为x,y格子的编号,然后找这些格子周围能走的格子,用deg[cnt]保存编号为cnt的格子周围能走的格子数,用G[cnt][i]保存编号为cnt的格子周围能走的第i个格子的编号,如果鬼的数量不足3,可以通过增加虚拟的格子,凑3个鬼,用来凑的鬼放在这个虚拟的格子里,并且设起点终点都是这个虚拟格子,且移动的方式只能原地不动。最后两个方向相遇两个d相加即求出最短路。

 1 #include <cstdio>
 2 #include <cctype>
 3 #include <queue>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 const int maxn = 150;
 8 const int maxs = 20;
 9 int w, h, n, deg[maxn], G[maxn][5], s[3], t[3];
10 char maze[20][20];
11 int d[maxn][maxn][maxn];
12 int d2[maxn][maxn][maxn];
13 
14 inline int ID(const int& a, const int& b, const int& c) {
15     return (a << 16) | (b << 8) | c;
16 }
17 
18 inline bool conflict(const int& a, const int& b, const int& a2, const int& b2) {
19     return a2 == b2 || (a2 == b && b2 == a);
20 }
21 
22 int DBfs() {
23     queue<int> q;
24     queue<int> q2;
25     queue<int> nxt;
26     memset(d, -1, sizeof(d));
27     memset(d2, -1, sizeof(d2));
28     q.push(ID(s[0], s[1], s[2]));
29     q2.push(ID(t[0], t[1], t[2]));
30     d[s[0]][s[1]][s[2]] = 0;
31     d2[t[0]][t[1]][t[2]] = 0;
32     while (!q.empty() && !q2.empty()) {
33         if (q.size() > q2.size()) swap(q, q2), swap(d, d2);
34         for (int ii = 0, sz = q.size(); ii < sz; ii++) {
35             int u = q.front(); q.pop();
36             int a = (u >> 16) & 0xff; int b = (u >> 8) & 0xff; int c = u & 0xff;
37             for (int i = 0; i < deg[a]; i++) {
38                 int a2 = G[a][i];
39                 for (int j = 0; j < deg[b]; j++) {
40                     int b2 = G[b][j];
41                     if (conflict(a, b, a2, b2)) continue;
42                     for (int k = 0; k < deg[c]; k++) {
43                         int c2 = G[c][k];
44                         if (conflict(a, c, a2, c2)) continue;
45                         if (conflict(b, c, b2, c2)) continue;
46                         if (d[a2][b2][c2] != -1) continue;
47                         d[a2][b2][c2] = d[a][b][c] + 1;
48                         if (d2[a2][b2][c2] >= 0) return d[a2][b2][c2] + d2[a2][b2][c2];
49                         nxt.push(ID(a2, b2, c2));
50                     }
51                 }
52             }
53         }
54         swap(q, nxt);
55     }
56     return -1;
57 }
58 
59 const int dx[5] = {1, -1, 0, 0, 0};
60 const int dy[5] = {0, 0, 1, -1, 0};
61 void init() {
62     int cnt = 0, x[maxn], y[maxn], id[maxs][maxs];    
63     for (int i = 0; i < h; i++)
64         for (int j = 0; j < w; j++)
65             if (maze[i][j] != #) {
66                 x[cnt] = i; y[cnt] = j; id[i][j] = cnt;
67                 if (islower(maze[i][j])) s[maze[i][j] - a] = cnt;
68                 else if (isupper(maze[i][j])) t[maze[i][j] - A] = cnt;
69                 cnt++;
70             }
71     for (int i = 0; i < cnt; i++) {
72         deg[i] = 0;
73         for (int dir = 0; dir < 5; dir++) {
74             int nx = x[i] + dx[dir], ny = y[i] + dy[dir];
75             if (nx < 0 || nx >= h || ny < 0 || ny >= w) continue;
76             if (maze[nx][ny] != #) G[i][deg[i]++] = id[nx][ny];
77         }
78     }
79     if (n <= 1) { deg[cnt] = 1; G[cnt][0] = cnt; s[1] = t[1] = cnt++; }
80     if (n <= 2) { deg[cnt] = 1; G[cnt][0] = cnt; s[2] = t[2] = cnt++; }
81 }
82 
83 int main() {
84     while (scanf("%d%d%d\n", &w, &h, &n) == 3 && n) {
85         for (int i = 0; i < h; i++)
86             fgets(maze[i], 20, stdin);
87         init();
88         printf("%d\n", DBfs());
89     }
90     return 0;
91 }

以上是关于UVa1601 The Morning after Halloween (双向广度优先搜索)的主要内容,如果未能解决你的问题,请参考以下文章

UVa1601 The Morning after Halloween(双向bfs)

The Morning after Halloween uva1601

UVA - 1601 - The Morning after Halloween

UVa1601 The Morning after Halloween (双向广度优先搜索)

UVa 1601 || POJ 3523 The Morning after Halloween (BFS || 双向BFS && 降维 && 状压)

UVA10596 Morning Walk欧拉回路