这是我写的第一个双重dfs, 参考了一下别人的思想.
主要是当箱子向四周扩展进行bfs时, 同时对人进行bfs.
具体描述如下:
当箱子(box_x, box_y)向某一个方向i前进到(box_x+dx[i], box_y[i]+dy[i]),
必须是人在位置(px-dx[i], py-dy[i])推动.
所以, 我们再对人进行bfs, 看能否从人的开始位置(people_x, people_y)前进到
(px-dx[i], py-dy[i]).
0ms的算法我大致看了一下, 和这个不同的是状态的保存, 我使用了string并作为已走
路径放在状态(State)结构体中, 要耗时一些.
如果你觉得这个程序有什么可以改进, 请你一定告诉我.
另外, 我发现这题跟你的初始方向设置有关系, poj数据不够大.
当我方向顺序设置如下时, WA
char dir[] = {'w', 'n', 'e', 's'};
char DIR[] = {'W', 'N', 'E', 'S'};
当我再改为如下顺序时, AC
char dir[] = {'n', 's', 'w', 'e' };
char DIR[] = {'N', 'S', 'W', 'E' };
说明poj的数据还是不够.
#include <iostream> #include <cstring> #include <cstdio> #include <string> #include <queue> using namespace std; bool visited[21][21][21][21]; bool people_visited[21][21]; bool map[21][21]; int r, c; int startpx, startpy, startbx, startby, endx, endy; int dx[] = {0, 0, -1, 1}; int dy[] = {-1, 1, 0, 0}; char dir[] = {'n', 's', 'w', 'e' }; char DIR[] = {'N', 'S', 'W', 'E' }; inline bool ok(int x, int y) { if(x < 0 || x >= c || y < 0 || y >= r || map[y][x] == false) return false; return true; } struct P { int x, y; string route; }; struct State{ int bx, by; int px, py; string route; }; string people_bfs(int startx, int starty, int endx, int endy, int bx, int by) { P temp; memset(people_visited, false, sizeof(people_visited)); queue<P> q; temp.x = startx, temp.y = starty, temp.route = ""; q.push(temp); people_visited[starty][startx] = true; while(!q.empty()) { P p = q.front(); q.pop(); if(p.x == endx && p.y == endy) return p.route; for(int i = 0; i < 4; ++i) { int tempx = p.x+dx[i], tempy = p.y+dy[i]; if(ok(tempx, tempy) && !people_visited[tempy][tempx] && !(tempx == bx && tempy == by)) { temp.x =tempx, temp.y = tempy, temp.route = p.route + dir[i]; q.push(temp); people_visited[tempy][tempx] = true; } } } return "*"; } string box_bfs() { State temp; memset(visited, false, sizeof(visited)); queue<State> q; temp.bx = startbx, temp.by = startby, temp.px = startpx, temp.py = startpy, temp.route = ""; q.push(temp); visited[startby][startbx][startpy][startpx] = true; while(!q.empty()) { State s = q.front(); q.pop(); if(s.bx == endx && s.by == endy) return s.route; for(int i = 0; i < 4; ++i) { int tempx1 = s.bx+dx[i], tempy1 = s.by+dy[i]; int tempx2 = s.bx-dx[i], tempy2 = s.by-dy[i]; if(ok(tempx1, tempy1) && ok(tempx2, tempy2) && !visited[tempy1][tempx1][s.by][s.bx]) { string str = people_bfs(s.px, s.py, tempx2, tempy2, s.bx, s.by); if(str != "*") { temp.bx = tempx1, temp.by = tempy1, temp.px = s.bx, temp.py = s.by, temp.route = s.route + str + DIR[i]; q.push(temp); visited[tempy1][tempx1][s.by][s.bx] = true; } } } } return "*"; } int main() { char ch; int cnt = 0; while(scanf("%d%d", &r, &c), r) { memset(map, true, sizeof(map)); for(int i = 0; i < r; ++i) for(int j = 0; j < c; ++j) { cin >> ch; if(ch == '#') map[i][j] = false; else if(ch == 'S') startpx = j, startpy = i; else if(ch == 'B') startbx = j, startby = i; else if(ch == 'T') endx = j, endy = i; } printf("Maze #%d/n", ++cnt); string str = box_bfs(); if(str != "*") cout << str << endl; else cout << "Impossible." << endl; printf("/n"); } return 0; }