双向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;
}