bfs是一层层的遍历下去,每多一层即为多走一步,因此只要遇到T就停,此时肯定是最小步数。
所以这两层bfs应为,先对箱子的最少步数进行bfs,从而求出推箱子所用最少步数;
然后箱子bfs内部嵌入人的bfs,从而箱子每走一步,判断一下这个移动能否由人来完成(由箱子的移动倒推人应该在的位置,看这个位置是否合理)。
一、http://tech.artyoo.me/?p=282
1 #include <map> 2 #include <set> 3 #include <queue> 4 #include <stack> 5 #include <math.h> 6 #include <time.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <iostream> 10 #include <limits.h> 11 #include <string.h> 12 #include <string> 13 #include <algorithm> 14 #include <iomanip> 15 #define read freopen("in.txt","r",stdin) 16 #define write freopen("out.txt","w",stdout) 17 using namespace std; 18 #define MAXSIZE 22 19 typedef struct { 20 int bx, by, px, py; 21 string path; 22 } Node; 23 typedef struct { 24 int x, y; 25 string path; 26 } Point; 27 int row, col; 28 char grid[MAXSIZE][MAXSIZE]; 29 bool vis[MAXSIZE][MAXSIZE][4], vis2[MAXSIZE][MAXSIZE]; 30 Node st; 31 int caseID; 32 queue<Node> qb; 33 queue<Point> qp; 34 35 const int dx[] = {-1, 1, 0, 0}; 36 const int dy[] = {0, 0, -1, 1}; 37 const char Dir[] = {'N', 'S', 'W', 'E'}; 38 const char dir[] = {'n', 's', 'w', 'e'}; 39 string person_path; 40 41 int Min(int a,int b){return a<b?a:b;} 42 int Max(int a,int b){return a>b?a:b;} 43 44 bool bfs_person(Point sp, Point ep, int bx, int by) { 45 person_path = ""; 46 memset(vis2, false, sizeof(vis2)); 47 while(!qp.empty()) qp.pop(); 48 sp.path = ""; 49 qp.push(sp); 50 vis2[sp.x][sp.y] = true; 51 while(!qp.empty()) { 52 Point now = qp.front(); qp.pop(); 53 if(now.x == ep.x && now.y == ep.y) { 54 person_path = now.path; 55 return true; 56 } 57 for(int d = 0; d < 4; d++) { 58 int x = now.x + dx[d]; 59 int y = now.y + dy[d]; 60 if(x >= 0 && x < row && y >= 0 && y < col && grid[x][y] != '#' && !(x == bx && y == by)) { 61 if(!vis2[x][y]) { 62 Point next; 63 next.x = x; 64 next.y = y; 65 next.path = now.path + dir[d]; 66 qp.push(next); 67 vis2[x][y] = true; 68 } 69 } 70 } 71 } 72 return false; 73 } 74 75 string bfs_box() { 76 memset(vis, false, sizeof(vis)); 77 while(!qb.empty()) qb.pop(); 78 qb.push(st); 79 while(!qb.empty()) { 80 Node now; 81 now = qb.front(); qb.pop(); 82 if(grid[now.bx][now.by] == 'T') { 83 return now.path; 84 } 85 for(int d = 0; d < 4; d++) { 86 int x = now.bx + dx[d]; 87 int y = now.by + dy[d]; 88 if(x >= 0 && x < row && y >= 0 && y < col && grid[x][y] != '#') { 89 if(!vis[x][y][d]) { 90 Point sp, ep; /* sp: 人的当前位置;ep:人要按当前方向推箱子的话必须得到达的位置 */ 91 sp.x = now.px; sp.y = now.py; 92 ep.x = now.bx; ep.y = now.by; 93 switch(d) { 94 case 0: ep.x += 1; break; 95 case 1: ep.x -= 1; break; 96 case 2: ep.y += 1; break; 97 case 3: ep.y -= 1; break; 98 } 99 if(ep.x >= 0 && ep.x < row && ep.y >= 0 && ep.y < col && grid[ep.x][ep.y] != '#') { 100 if(bfs_person(sp, ep, now.bx, now.by)) { 101 Node next; 102 next.bx = x; next.by = y; 103 next.px = now.bx; next.py = now.by; 104 next.path = now.path + person_path + Dir[d]; 105 qb.push(next); 106 vis[x][y][d] = true; 107 } 108 } 109 } 110 } 111 } 112 } 113 return "Impossible."; 114 } 115 116 int main() { 117 read; write; 118 caseID = 0; 119 while(scanf("%d%d", &row, &col) && row && col) { 120 getchar(); 121 for(int i = 0; i < row; i++) { 122 gets(grid[i]); 123 } 124 for(int i = 0; i < row; i++) { 125 for(int j = 0; j < col; j++) { 126 if(grid[i][j] == 'B') { 127 st.bx = i; 128 st.by = j; 129 grid[i][j] = '.'; 130 } else if(grid[i][j] == 'S') { 131 st.px = i; 132 st.py = j; 133 grid[i][j] = '.'; 134 } 135 } 136 } 137 st.path = ""; 138 printf("Maze #%d\n", ++caseID); 139 cout << bfs_box() << endl << endl; 140 } 141 return 0; 142 }
二、http://www.cnblogs.com/Missa/archive/2012/10/07/2714435.html
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 #include <queue> 6 #include <string> 7 8 using namespace std; 9 10 #define MAXN 22 11 char P[4] = { 'N', 'S', 'W', 'E' }; 12 char M[4] = { 'n', 's', 'w', 'e' }; 13 int R, C; 14 int dir[4][2] = { -1, 0, 1, 0, 0, -1, 0, 1 };//之前当成坐标轴里x,y坐标来算,怎么都不对。后来发现原来x,y是行数和列数。x-1代表到上一行去,即N。 15 char map[MAXN][MAXN]; 16 struct point 17 { 18 int x, y; 19 int p_x, p_y;//当前状态person所在的地方 20 string ans; 21 }; 22 bool isok(int x, int y) 23 { 24 if (x >= 0 && x < R && y >= 0 && y < C && map[x][y] != '#') 25 return true; 26 return false; 27 } 28 string tmp; 29 bool bfs_person(point en, point cu) 30 { 31 tmp = ""; 32 point st; 33 st.x = en.p_x; 34 st.y = en.p_y; 35 st.ans = ""; 36 queue<point>q; 37 bool vis[MAXN][MAXN]; 38 memset(vis, 0, sizeof(vis)); 39 while (!q.empty()) 40 q.pop(); 41 q.push(st); 42 while (!q.empty()) 43 { 44 point cur, next; 45 cur = q.front(); 46 q.pop(); 47 if (cur.x == en.x && cur.y == en.y) 48 { 49 tmp = cur.ans; 50 return true; 51 } 52 for (int i = 0; i < 4; i++) 53 { 54 next = cur; 55 next.x = cur.x + dir[i][0]; 56 next.y = cur.y + dir[i][1]; 57 if (!isok(next.x, next.y)) continue; 58 if (next.x == cu.x && next.y == cu.y) continue;//cu.x,cu.y is the location of the box. 59 if (vis[next.x][next.y]) continue;//来过的地方就不能在来了???????莫非bfs都是这样? 60 vis[next.x][next.y] = 1; 61 next.ans = cur.ans + M[i]; 62 //cout << "M[i] "<<M[i] << endl; 63 //cout << "cur.ans " << cur.ans << endl; 64 q.push(next); 65 } 66 } 67 return false; 68 } 69 string bfs_box() 70 { 71 bool vis[MAXN][MAXN][4];//某点四个方向是否访问!!0==N,1==S,2==W,3==E 72 point st; 73 st.x = st.y = -1; 74 st.p_x = st.p_y = -1; 75 st.ans = ""; 76 for (int i = 0; i < R && (st.x == -1 || st.p_x == -1); i++) 77 for (int j = 0; j < C && (st.x == -1 || st.p_x == -1); j++) 78 if (map[i][j] == 'B') 79 { 80 st.x = i; 81 st.y = j; 82 map[i][j] = '.'; 83 } 84 else if (map[i][j] == 'S') 85 { 86 st.p_x = i; 87 st.p_y = j; 88 map[i][j] = '.'; 89 } 90 //---------------------------------------- 91 //cout<<"st.x="<<st.x<<" st.y="<<st.y<<" st.p_x="<<st.p_x<<" st.p_y="<<st.p_y<<endl; 92 //---------------------------------------- 93 queue<point> q; 94 while (!q.empty()) 95 q.pop(); 96 q.push(st); 97 memset(vis, 0, sizeof(vis)); 98 while (!q.empty()) 99 { 100 point cur = q.front(); q.pop(); 101 //---------------------------------------- 102 // cout<<"cur.x="<<cur.x<<" cur.y="<<cur.y<<" cur.p_x="<<cur.p_x<<" cur.p_y="<<cur.p_y<<endl; 103 // cout<<"-----------------------------\n"; 104 //---------------------------------------- 105 point next, pre; 106 if (map[cur.x][cur.y] == 'T') 107 return cur.ans; 108 for (int i = 0; i < 4; i++) 109 { 110 next = cur; 111 next.x = cur.x + dir[i][0]; 112 next.y = cur.y + dir[i][1]; 113 if (!isok(next.x, next.y)) 114 continue; 115 if (vis[next.x][next.y][i]) 116 continue; 117 pre = cur; 118 switch (i) 119 { 120 case 0: pre.x = cur.x + 1; break; 121 case 1: pre.x = cur.x - 1; break; 122 case 2: pre.y = cur.y + 1; break; 123 case 3: pre.y = cur.y - 1; break; 124 } 125 if (!bfs_person(pre, cur))//搜寻人是否能走到特定的位置 126 continue; 127 vis[next.x][next.y][i] = 1; 128 next.ans = cur.ans + tmp; 129 next.ans = next.ans + P[i]; 130 cout << "P[i] " << P[i] << endl; 131 cout <<"cur--"<< cur.x << "," << cur.y << ";" << cur.p_x << "," << cur.p_y << endl; 132 cout <<"next--" << next.x << "," << next.y << ";" << next.p_x << "," << next.p_y << endl; 133 next.p_x = cur.x; next.p_y = cur.y; 134 q.push(next); 135 } 136 } 137 return "Impossible."; 138 } 139 140 int main() 141 { 142 int cas = 1; 143 while (scanf("%d%d", &R, &C) && (R + C)) 144 { 145 getchar(); 146 for (int i = 0; i < R; i++) 147 gets(map[i]); 148 149 //--------------------------------------- 150 // for(int i=0;i<R;i++) 151 // cout<<map[i]<<endl; 152 //---------------------------------------- 153 154 printf("Maze #%d\n", cas++); 155 //printf("%s\n",bfs_box()); 156 cout << bfs_box() << endl << endl; 157 } 158 return 0; 159 }