题目链接:POJ 1915 Knight Moves
双向BFS的优点上篇文章有。vis = 2表示从终点开始的搜索已经达到过这一点,vis = 1表示从源点开始的搜索已经达到过这一点,vis = 0表示没搜到过这一点。
一定要按层扩展,具体原因可以看这里,这篇博客还写了一个优化办法,我没看懂就没加,poj数据太水了,下午没按层扩展也过了。。
#include <iostream> #include <cstring> #include <cstdio> #include <queue> using namespace std; const int MAX_N = 300 + 30; const int INF = (1 << 29); struct Point { int x, y, dis; Point(int x = 0, int y = 0, int dis = 0) : x(x), y(y), dis(dis) {}; }; int vis[MAX_N][MAX_N], dis[MAX_N][MAX_N];; int fx[8] = {2, 2, -2, -2, 1, 1, -1, -1}; int fy[8] = {1, -1, 1, -1, 2, -2, 2, -2}; int n, res; queue <Point> Qs, Qe; void BFS() { Point a; int dx, dy, now = 0; while(!Qs.empty() && !Qe.empty()) { while(Qs.front().dis == now) { a = Qs.front(); Qs.pop(); for(int i = 0; i < 8; i++) { dx = a.x + fx[i], dy = a.y + fy[i]; if(dx >= 0 && dy >= 0 && dx < n && dy < n && vis[dx][dy] != 1) { if(vis[dx][dy] == 2) { res = a.dis + 1 + dis[dx][dy]; return ; } Qs.push(Point(dx, dy, a.dis + 1)); vis[dx][dy] = 1; dis[dx][dy] = a.dis + 1; } } } while(Qe.front().dis == now) { a = Qe.front(); Qe.pop(); for(int i = 0; i < 8; i++) { dx = a.x + fx[i], dy = a.y + fy[i]; if(dx >= 0 && dy >= 0 && dx < n && dy < n && vis[dx][dy] != 2) { if(vis[dx][dy] == 1) { res = a.dis + 1 + dis[dx][dy]; return ; } Qe.push(Point(dx, dy, a.dis + 1)); vis[dx][dy] = 2; dis[dx][dy] = a.dis + 1; } } } now++; } } int main() { //freopen("in.txt", "r", stdin); int T; scanf("%d", &T); Point _start, _end; while(T--) { scanf("%d", &n); scanf("%d%d", &_start.x, &_start.y); scanf("%d%d", &_end.x, &_end.y); res = INF; memset(vis, 0, sizeof(vis)); if(_start.x == _end.x && _start.y == _end.y) { printf("0\n"); continue; } while(!Qs.empty()) Qs.pop(); while(!Qe.empty()) Qe.pop(); Qs.push(_start), Qe.push(_end); dis[_start.x][_start.y] = dis[_end.x][_end.y] = 0; vis[_start.x][_start.y] = 1; vis[_end.x][_end.y] = 2; BFS(); printf("%d\n", res); } return 0; }