这题说是可以用双向bfs,为了看看双向到底能多牛,我做了单向和单向
第一个图是单向bfs所花的时间:
第二个图是双向bfs所花的时间
感觉……没啥特别大的区别啊^而且双向写起来有点麻烦,我写的时候漏了好多东西
直接上双向的代码好了,这个双向还是好理解的,
#include<iostream>
#include<string>
#include<queue>
#define M 330
using namespace std;
int px[8]={-1,1,-2,2,-2,2,-1,1};
int py[8]={-2,-2,-1,-1,1,1,2,2};
int n,sx,sy,ex,ey,vs[M][M],ve[M][M],vt[M][M];
typedef struct
{
int x,y;
int time;
}chess;
int bfs()
{
int i,j;
memset(ve,1,sizeof(ve));
memset(vs,1,sizeof(vs));
for(i=2;i<=n+1;i++)
for(j=2;j<=n+1;j++)
ve[i][j]=vs[i][j]=0;
chess s,e,temp;
queue<chess> sq,eq;
s.time=e.time=0; //初始化操作
s.x=sx;s.y=sy;
e.x=ex;e.y=ey;
vs[s.x][s.y]=ve[e.x][e.y]=1; //vs和ve代表s队列和e队列走过的访问标识
vt[s.x][s.y]=vt[e.x][e.y]=0; //vt代表走到这格所花的时间,先到的先赋值
if(sx==ex&&sy==ey) //如果一开始就相同返回0
return 0;
sq.push(s);
eq.push(e);
while(1)
{
s=sq.front(); sq.pop();
e=eq.front(); eq.pop();
for( i=0;i<8;i++)
{
temp=s; //对s队列操作
temp.x+=px[i];
temp.y+=py[i];
temp.time++;
if(vs[temp.x][temp.y]==0)
{
if(ve[temp.x][temp.y]==1) //如果自己的下一步已经被e队列走过,说明相遇
return vt[temp.x][temp.y]+temp.time;
sq.push(temp);
vs[temp.x][temp.y]=1;
vt[temp.x][temp.y]=temp.time; //存储自己走到这格所花的时间
}
//对e队列的操作与s类似,e改成s,s改成e即可
temp=e;
temp.x+=px[i];
temp.y+=py[i];
temp.time++;
if(ve[temp.x][temp.y]==0)
{
if(vs[temp.x][temp.y]==1)
return vt[temp.x][temp.y]+temp.time;
eq.push(temp);
ve[temp.x][temp.y]=1;
vt[temp.x][temp.y]=temp.time;
}
}
}
}
int main()
{
int t,i,j,ans;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
sx+=2;sy+=2;ex+=2;ey+=2; //每一点+2可以防止数组为负
ans=bfs();
printf("%d\n",ans);
}
return 0;
}