ZOJ 1649 - Rescue BFS/优先队列
在HDOJ上提交通过以后,再在zoj上提交,结果得到了无数个WA,后来发现有一种情况我并没有考虑到
有几个关键的地方需要注意:
1. Angel的朋友不只有一个,可能有多个
2. guard的存在可能会破坏广度优先树
解决办法:
BFS的做法:必须要保存guard与可行点‘.’的插入同步,因为guard的costTime不同,应该先不改变其坐标,costTime增加一以后,设为已被访问,‘x’变为‘.’或者‘#’,重新入队,此时,guard已被插入到队列的尾部,这样一来,guard与‘.’就可以同步了
View Code
1 #include <math.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <memory.h>
6
7 char maze[210][210];
8 int vis[210][210];
9 int dx[] = {-1, 1, 0, 0};
10 int dy[] = {0, 0, -1, 1};
11 int nNum, mNum, i, j, sx, sy;
12
13 struct Node
14 {
15 int x;
16 int y;
17 int step;
18 };
19
20 int IsInBound(int x, int y)
21 {
22 if (x<0 || y<0 || x>=nNum || y>=mNum)
23 {
24 return 0;
25 }
26
27 return 1;
28 }/* IsInBound */
29
30 void BFS()
31 {
32 int k;
33 int front = -1;
34 int rear = -1;
35 int isSolve = 0;
36 struct Node dir, cur;
37 struct Node q[40010] = {0};
38
39 cur.x = sx;
40 cur.y = sy;
41 cur.step = 0;
42 q[++rear] = cur;
43
44 vis[sx][sy] = 1;
45 while (front != rear)
46 {
47 cur = q[++front];
48 if (maze[cur.x][cur.y] == 'r')
49 {
50 isSolve = 1;
51 break;
52 }
53
54 /**
55 * 因为没有考虑这个,导致WA了无数次,
56 * guards的存在可能会破坏广度优先树,因为是
57 * 它的costTime与可行路‘.’的costTime不同步
58 *
59 * 先不改变当前的坐标,干掉guard以后,将x变为可行
60 * 路径‘.’,在压入队列中,这样可以保持同步
61 ***/
62 if (maze[cur.x][cur.y] == 'x')
63 {
64 ++cur.step;
65 vis[cur.x][cur.y] = 1;
66 maze[cur.x][cur.y] = '.';
67 q[++rear] = cur;
68 }
69 else
70 {
71 for (k=0; k<4; ++k)
72 {
73 dir.x = cur.x + dx[k];
74 dir.y = cur.y + dy[k];
75 dir.step = cur.step + 1;
76
77 if (!vis[dir.x][dir.y] && maze[dir.x][dir.y]!='#'
78 && IsInBound(dir.x, dir.y))
79 {
80 vis[dir.x][dir.y] = 1;
81 q[++rear] = dir;
82 }
83 }/* End of For */
84 }
85 }/* End of While */
86 if (isSolve)
87 {
88 printf("%d\n", cur.step);
89 }
90 else
91 {
92 printf("Poor ANGEL has to stay in the prison all his life.\n");
93 }
94 }/* BFS */
95
96 int main()
97 {
98 while (2 == scanf("%d %d", &nNum, &mNum))
99 {
100 getchar();
101 memset(maze, 0, sizeof(maze));
102 memset(vis, 0, sizeof(vis));
103
104 for (i=0; i<nNum; ++i)
105 {
106 scanf("%s", maze[i]);
107 }/* End of For */
108
109 /*
110 * 因为Angel不只有一个Friend
111 * 可能有多个friends
112 */
113 for (i=0; i<nNum; ++i)
114 {
115 for (j=0; j<mNum; ++j)
116 {
117 if (maze[i][j] == 'a')
118 { /* 找出Angel的位置,从Angel的位置开始探索 */
119 sx = i, sy = j;
120 }
121 }
122 }/* End of For */
123
124 BFS();
125 }/* End of While */
126
127 return 0;
128 }
第二种方法是:利用优先队列,按可行点时间的大少,costTime少的优先,即最少值优先,如此一来,guard的访问点就会插入到队列的队尾了
View Code
1 #include <queue>
2 #include <cstdio>
3 #include <cstdlib>
4 #include <cstring>
5 #include <memory.h>
6 using namespace std;
7
8 char maze[210][210];
9 int vis[210][210];
10 int i, j, nNum, mNum, sx, sy;
11 int dx[] = {-1, 1, 0, 0};
12 int dy[] = {0, 0, -1, 1};
13
14 struct Node
15 {
16 int x, y, step;
17
18 bool operator < (const Node &a) const
19 {
20 return step > a.step;
21 }
22 };
23
24 int IsInBound(int x, int y)
25 {
26 if (x<0 || y<0 || x>=nNum || y>=mNum)
27 {
28 return 0;
29 }
30
31 return 1;
32 }/* IsInBound */
33
34 void BFS()
35 {
36 int k, isSolve = 0;
37 Node cur, next;
38 priority_queue<Node> q;
39
40 cur.x = sx;
41 cur.y = sy;
42 cur.step = 0;
43 q.push(cur);
44
45 vis[sx][sy] = 1;
46 while (!q.empty())
47 {
48 cur = q.top();
49 q.pop();
50
51 if (maze[cur.x][cur.y] == 'r')
52 {
53 isSolve = 1;
54 break;
55 }
56
57 for (k=0; k<4; ++k)
58 {
59 next.x = cur.x + dx[k];
60 next.y = cur.y + dy[k];
61 next.step = cur.step + 1;
62
63 if (IsInBound(next.x, next.y) && !vis[next.x][next.y]
64 && maze[next.x][next.y]!='#')
65 {
66 vis[next.x][next.y] = 1;
67 if (maze[next.x][next.y] == 'x')
68 {
69 ++next.step;
70 }
71
72 q.push(next);
73 }
74 }/* End of For */
75 }/* End of While */
76 if (isSolve)
77 {
78 printf("%d\n", cur.step);
79 }
80 else
81 {
82 printf("Poor ANGEL has to stay in the prison all his life.\n");
83 }
84 }/* BFS */
85
86 int main()
87 {
88 while (2 == scanf("%d %d", &nNum, &mNum))
89 {
90 getchar();
91 memset(vis, 0, sizeof(vis));
92 memset(maze, 0, sizeof(maze));
93
94 for (i=0; i<nNum; ++i)
95 {
96 scanf("%s", maze[i]);
97 }/* End of For */
98
99 for (i=0; i<nNum; ++i)
100 {
101 for (j=0; j<mNum; ++j)
102 {
103 if (maze[i][j] == 'a')
104 {
105 sx = i, sy = j;
106 }
107 }
108 }/* End of For */
109
110 BFS();
111 }/* End of While */
112
113 return 0;
114 }