题目描述(翻译)
somurolov先生,精彩的象棋玩家。声称任何人他都可以从一个位置到另一个骑士这么快。你能打败他吗?
问题
你的任务是写一个程序来计算一个骑士达到从另一点所需要的最少步数,这样你就有机会被比somurolov。
对于不熟悉象棋的人,可能的骑士动作如图1所示。
输入
输入开始与一个单一的行本身的情况下。
下一步跟踪N个场景。每个场景由三行包含整数。第一行指定棋盘边的长度L(4 < L = < 300)。整个板尺寸L×L的第二和第三行包含整数对{ 0,…,L-1 } * { 0,…,L-1 }指定开始和结束位置的骑士。整数由一个空格隔开。您可以假定这些位置是该方案的棋盘上的有效位置.。
输出
对于输入的每一个场景,你必须计算从起点到终点的最小的骑士移动量.。如果起点和终点相等,距离为零。距离必须写在一行。
样例输入
3
8
0 0
7 0
100
0 0
30 50
10
1 1
1 1
样例输出
5
28
0
思路
典型的马走日的变种,只是将DFS改成了BFS而已
代码实现
#include<iostream>
#include<cstring>
using namespace std;
int head=0,tail=1,q,nextx,nexty,n,m,startx,starty,overx,overy;
int a[100005],b[100005],pre[100005],x[8]={-2,-1,1,2,2,1,-1,-2},y[8]={1,2,2,1,-1,-2,-2,-1},c;
bool mark[305][305];
void print(int d)
{
if(pre[d]!=0)print(pre[d]);
c++;
}
bool chek(int qx,int qy)
{
if(qx<=m-1&&qy<=m-1&&qx>=0&&qy>=0)return 1;
return 0;
}
void dfs()
{
memset(mark,0,sizeof(mark));
a[1]=startx;
b[1]=starty;
mark[startx][starty]=1;
pre[1]=0;
head=0;tail=1;
while(head!=tail)
{
head++;
for(int i=0;i<=7;i++)
{
nextx=a[head]+x[i];
nexty=b[head]+y[i];
if(!mark[nextx][nexty]&&chek(nextx,nexty))
{
tail++;
a[tail]=nextx;
b[tail]=nexty;
pre[tail]=head;
mark[nextx][nexty]=1;
if(a[tail]==overx&&b[tail]==overy)
{
print(tail);
printf("%d\n",c-1);
return ;
}
}
}
}
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
c=0;
scanf("%d",&m);
scanf("%d%d%d%d",&startx,&starty,&overx,&overy);
if(startx==overx&&starty==overy)
{
printf("0\n");
continue;
}
dfs();
}
}