bfs ZOJ 1649 Rescue
刚看到题目时,觉得题目不难,感觉就一个bfs,只不过多了guard这个判断
结果WA了无数次, 想不出原因,后来查看别人解题报告,才发现自己处理那个guard时候出错了,
尽管写程序我已经留意这个问题,主要原因是自己思路错了。
刚开始思路是,在坐标改变时判断遇到guard就直接step 再加个1, 再插入队列。这个是致命错误。
原因会抢占原属于最短路径的某些地格,导致计算出来最小值偏大。
看了别人解题报告后,就直接单独出来判断,当前地格是guard的话,坐标不变先,把该地格改为“.”可通行
把当前的point插入队列,这样不会抢占了。下次会再次回到这个坐标开始搜索。
7 8
#.#####.
#..#..r.
#..#..x.
..#..#x#
#...##x.
.#..axx.
........
这个数据,正确答案是8, 按我开始的思路,计算出是11,因为它搜到的是路XXXXXa,
r下面的X先于.入队列,导致r下面的x左边的第二个. 被抢占了,从而导致计出最短路数值偏错
Rescue
1 #include<iostream>
2 #include <queue>
3 using namespace std;
4
5 struct point
6 {
7 int x;
8 int y;
9 int step;
10 };
11
12 point oper[4] = { {0, -1}, {0, 1}, {1, 0}, {-1, 0}};
13
14 char cango[200][200];
15 bool isvisit[200][200];
16 point friends[1000];
17 int friendsnum;
18 point P;
19 point S;
20 point goal;
21 queue<point> Q;
22 int row;
23 int col;
24 bool isfind = false;
25
26 void bfs();
27 int minstep = 50000;
28 int main()
29 {
30 int num;
31 char a;
32 freopen("test.txt","r", stdin);
33
34 while (cin >> row >> col)
35 {
36 friendsnum = 0;
37 minstep = 50000;
38 isfind =false;
39 for (int i = 0; i < row; i++)
40 {
41 for (int j = 0; j < col; j++)
42 {
43 isvisit[i][j] = false;
44 cin >> cango[i][j];
45 if (cango[i][j] == 'r')
46 {
47 friends[friendsnum].x = i;
48 friends[friendsnum].y = j;
49 friendsnum++;
50 }
51 if (cango[i][j] == 'a')
52 {
53 goal.x = i;
54 goal.y = j;
55 }
56 }
57 }
58
59 for (int i = 0; i < friendsnum; i++)
60 {
61 for (int i = 0; i < row; i++)
62 for (int j = 0; j < col; j++)
63 isvisit[i][j] = false;
64 S.x = friends[i].x;
65 S.y = friends[i].y;
66 S.step = 0;
67 bfs();
68 }
69
70
71 if (!isfind)
72 cout << "Poor ANGEL has to stay in the prison all his life." << endl;
73 else
74 cout << minstep << endl;
75 }
76 return 0;
77 }
78
79
80 void bfs()
81 {
82 while(!Q.empty())
83 Q.pop();
84
85 Q.push(S);
86 isvisit[S.x][S.y] = true;
87
88 while (!Q.empty())
89 {
90 S = Q.front();
91 Q.pop();
92
93 if (S.x == goal.x && S.y == goal.y && S.step < minstep)
94 {
95 minstep = S.step;
96 isfind = true;
97 return;
98 }
99
100 //遇到guard的情况单独考虑
101 //先不改变自己坐标,先把x清掉,累计步数+1,再在队列插入自己
102 //原因是保持同步,不然会出现这个路径霸占了实际最短路径的某些位置,导致错误
103 if (cango[S.x][S.y] == 'x')
104 {
105 S.step++;
106 cango[S.x][S.y] = '.';
107 isvisit[S.x][S.y] = true;
108 Q.push(S);
109
110 }
111 else
112 {
113 for (int i = 0; i < 4; i++)
114 {
115 P.x = S.x + oper[i].x;
116 P.y = S.y + oper[i].y;
117 P.step = S.step + 1;
118 if (P.x>=0 && P.x <row && P.y >= 0 && P.y <col && !isvisit[P.x][P.y]
119 && cango[P.x][P.y] != '#' && cango[P.x][P.y] != 'r' )
120 {
121 //不能这样判断遇到guard的情况
122 //if (cango[P.x][P.y] == 'x')
123 // P.step++;
124 isvisit[P.x][P.y] = true;
125 Q.push(P);
126 }
127
128 }
129 }
130 }
131 }