用两个队列 Q和 P,Q用来储存正向搜索的节点,P用来储存逆向搜索的节点;在地图中进行染色,正向搜索到的节点染色为1,逆向搜索到的节点染色为2,当正向搜索到染色为2的节点时或者逆向搜索到染色为1的节点时表示两者相遇;还要标从起点(或终点)到当前位置所需要的步数,当相遇的时候起点到该点的距离加上重点到该点的距离就是起点到终点的距离。
代码如下
#include<iostream>
#include<queue>
#include<cstdio>
using namespace std;
const int maxn = 310;
typedef pair<int,int> node;
int n,fstep[maxn][maxn],bstep[maxn][maxn];///分别记录正向搜索和逆向搜索步数
int mv[8][2] = {-1,-2,-2,-1,-2,1,-1,2,1,2,2,1,2,-1,1,-2};
int dbfs(node a,node b)
{
if(a.first == b.first && a.second == b.second)
return 0;
queue<node>q1,q2;
for(int i = 0;i < n; i++)
for(int j = 0;j <n; j++)
fstep[i][j] = bstep[i][j] = -1;///步数初始化
fstep[a.first][a.second] = bstep[b.first][b.second] = 0;
q1.push(a);
q2.push(b);
while(!q1.empty() || !q2.empty())
{
node t,t1,t2;
if(!q1.empty())
{
t1 = q1.front();
q1.pop();
for(int i = 0;i < 8; i++)
{
t.first = t1.first + mv[i][0];
t.second = t1.second + mv[i][1];
if(t.first >= 0 && t.first < n && t.second >= 0 && t.second < n)
{
if(fstep[t.first][t.second] == -1)
{
fstep[t.first][t.second] = fstep[t1.first][t1.second] + 1;
q1.push(t);
}
if(bstep[t.first][t.second] != -1)///判断是否生成了同一子状态
return fstep[t.first][t.second] + bstep[t.first][t.second];
///达到子状态的那一步上面已经走了,故返回值不需要再加一
}
}
}
if(!q2.empty())
{
t2 = q2.front();
q2.pop();
for(int i = 0;i < 8; i++)
{
t.first = t2.first + mv[i][0];
t.second = t2.second + mv[i][1];
if(t.first >= 0 && t.first < n && t.second >= 0 && t.second < n)
{
if(bstep[t.first][t.second] == -1)
{
bstep[t.first][t.second] = bstep[t2.first][t2.second] + 1;
q2.push(t);
}
if(fstep[t.first][t.second] != -1)
return bstep[t.first][t.second] + fstep[t.first][t.second];
}
}
}
}
}
int main()
{
int t,ans;
node a,b;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
scanf("%d %d %d %d",&a.first,&a.second,&b.first,&b.second);
ans = dbfs(a,b);
printf("%d\n",ans);
}
return 0;
}