POJ1915Knight Moves(单向BFS + 双向BFS)
单向bfs就是水题
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 const int INF = 0x3f3f3f3f; 8 const int Max = 300 + 5; 9 struct Node 10 { 11 int x, y; 12 }; 13 int g[Max][Max]; 14 int vis[Max][Max]; 15 int n, sx, sy, ex, ey; 16 int gx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; 17 int gy[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; 18 bool in_bound(int x, int y) 19 { 20 if (x >= 0 && y >= 0 && x < n && y < n) 21 return true; 22 return false; 23 } 24 int bfs(int sx, int sy) 25 { 26 Node node, temp; 27 node.x = sx; 28 node.y = sy; 29 vis[sx][sy] = 0; 30 queue<Node> q; 31 q.push(node); 32 while (!q.empty()) 33 { 34 node = q.front(); 35 q.pop(); 36 if (node.x == ex && node.y == ey) 37 return vis[ex][ey]; 38 for (int i = 0; i < 8; i++) 39 { 40 int fx = node.x + gx[i]; 41 int fy = node.y + gy[i]; 42 if (in_bound(fx, fy) && vis[fx][fy] > vis[node.x][node.y] + 1) 43 { 44 temp.x = fx; 45 temp.y = fy; 46 vis[fx][fy] = vis[node.x][node.y] + 1; 47 q.push(temp); 48 } 49 } 50 } 51 return -1; 52 } 53 int main() 54 { 55 int test; 56 scanf("%d", &test); 57 while (test--) 58 { 59 scanf("%d", &n); 60 scanf("%d%d%d%d", &sx, &sy, &ex, &ey); 61 memset(vis, INF, sizeof(vis)); 62 printf("%d\n", bfs(sx, sy)); 63 } 64 return 0; 65 }
做这题主要是学着写双向bfs;
分别从起点和终点开始搜,如果重合即找到
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; const int Max = 300 + 5; struct Node { int x, y; bool step; }; // 这个step的意思之前没搞明白,他其实就是指的 在某一步下可以走到点 //开始讲 start.step设为true,因此在只能走一次 8 个点,然后8个点都是第一步走的,然后把最后一个点的step设为true,当你走第二部时候,就是 do { 以这个点扩展 8 步} while ( !current.step) step控制了层数。 int g[Max][Max]; int vis[Max][Max]; int n, sx, sy, ex, ey; int gx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; int gy[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; bool in_bound(int x, int y) { if (x >= 0 && y >= 0 && x < n && y < n) return true; return false; } int bfs() { if (sx == ex && sy == ey) return 0; Node start, finish; start.x = sx; start.y = sy; start.step = true; finish.x = ex; finish.y = ey; finish.step = true; vis[sx][sy] = 1; vis[ex][ey] = 2; queue<Node> frontSearch; queue<Node> backSearch; int fstep = 0, bstep = 0; frontSearch.push(start); backSearch.push(finish); Node current; while (!frontSearch.empty() || !backSearch.empty()) { if (!frontSearch.empty()) { do { current = frontSearch.front(); frontSearch.pop(); for (int i = 0; i < 8; i++) { int fx = current.x + gx[i]; int fy = current.y + gy[i]; if (in_bound(fx, fy)) { if (vis[fx][fy] == 2) { return fstep + bstep + 1; } if (!vis[fx][fy]) { vis[fx][fy] = 1; Node temp; temp.x = fx; temp.y = fy; temp.step = false; frontSearch.push(temp); } } } }while(current.step == false); fstep++; current = frontSearch.front(); frontSearch.pop(); current.step = true; // 为了让最后队列中最后一个数step为true,先将队首拿出来,修改step,然后在入队 frontSearch.push(current); } if (!backSearch.empty()) { do { current = backSearch.front(); backSearch.pop(); for (int i = 0; i < 8; i++) { int fx = current.x + gx[i]; int fy = current.y + gy[i]; if (in_bound(fx, fy)) { if (vis[fx][fy] == 1) { return bstep + fstep + 1; } if (!vis[fx][fy]) { vis[fx][fy] = 2; Node temp; temp.x = fx; temp.y = fy; temp.step = false; backSearch.push(temp); } } } } while(current.step == false); bstep++; current = backSearch.front(); backSearch.pop(); current.step = true; backSearch.push(current); } } return -1; } int main() { int test; scanf("%d", &test); while (test--) { scanf("%d", &n); scanf("%d%d%d%d", &sx, &sy, &ex, &ey); memset(vis, 0, sizeof(vis)); printf("%d\n", bfs()); } return 0; }
第二种 双向bfs写法:
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 const int INF = 0x3f3f3f3f; 8 const int Max = 300 + 5; 9 struct Node 10 { 11 int x, y; 12 bool step; 13 }; 14 int g[Max][Max]; 15 int fvis[Max][Max], bvis[Max][Max]; 16 int n, sx, sy, ex, ey; 17 int gx[8] = {-1, -2, -2, -1, 1, 2, 2, 1}; 18 int gy[8] = {-2, -1, 1, 2, 2, 1, -1, -2}; 19 bool in_bound(int x, int y) 20 { 21 if (x >= 0 && y >= 0 && x < n && y < n) 22 return true; 23 return false; 24 } 25 int bfs() 26 { 27 if (sx == ex && sy == ey) 28 return 0; 29 Node start, finish; 30 start.x = sx; 31 start.y = sy; 32 start.step = true; 33 finish.x = ex; 34 finish.y = ey; 35 finish.step = true; 36 fvis[sx][sy] = 0; 37 bvis[ex][ey] = 0; 38 queue<Node> frontSearch; 39 queue<Node> backSearch; 40 int fstep = 0, bstep = 0; 41 frontSearch.push(start); 42 backSearch.push(finish); 43 Node current; 44 while (!frontSearch.empty() || !backSearch.empty()) 45 { 46 int frontSize = (int) frontSearch.size(); 47 while (frontSize--) // 直接将这一个队 全都 拿出来更新,就相当于上一中的step一样,控制搜索的层次 48 { 49 current = frontSearch.front(); 50 frontSearch.pop(); 51 52 for (int i = 0; i < 8; i++) 53 { 54 int fx = current.x + gx[i]; 55 int fy = current.y + gy[i]; 56 if (in_bound(fx, fy)) 57 { 58 if (bvis[fx][fy] != -1) // 如果 倒着搜 已经搜到了,返回 59 return fvis[current.x][current.y] + 1 + bvis[fx][fy]; 60 if (fvis[fx][fy] == -1) //否则正着+1 61 { 62 Node temp; 63 temp.x = fx; 64 temp.y = fy; 65 fvis[fx][fy] = fvis[current.x][current.y] + 1; 66 frontSearch.push(temp); 67 } 68 } 69 } 70 } 71 int backSize = (int) backSearch.size(); 72 while (backSize--) 73 { 74 current = backSearch.front(); 75 backSearch.pop(); 76 77 for (int i = 0; i < 8; i++) 78 { 79 int fx = current.x + gx[i]; 80 int fy = current.y + gy[i]; 81 if (in_bound(fx, fy)) 82 { 83 if (fvis[fx][fy] != -1) 84 { 85 return bvis[current.x][current.y] + 1 + fvis[fx][fy]; 86 } 87 if (bvis[fx][fy] == -1) 88 { 89 Node temp; 90 temp.x = fx; 91 temp.y = fy; 92 bvis[fx][fy] = bvis[current.x][current.y] + 1; 93 backSearch.push(temp); 94 } 95 } 96 } 97 } 98 } 99 return -1; 100 } 101 int main() 102 { 103 int test; 104 scanf("%d", &test); 105 while (test--) 106 { 107 scanf("%d", &n); 108 scanf("%d%d%d%d", &sx, &sy, &ex, &ey); 109 memset(fvis, -1, sizeof(fvis)); 110 memset(bvis, -1, sizeof(bvis)); 111 printf("%d\n", bfs()); 112 } 113 return 0; 114 }