题目大意:给一个边长为len的棋盘,然后给出起点和终点的坐标,求马从起点到终点最少需要走几步!
题解:这个题的题意是很好理解的,要求我们求最少需要走的步数,我们在这可以想到用bfs来解决这个问题,由于在这个棋盘中,马棋有八种路可以选择进行跳跃,所以开辟两个方向数组xx[]和yy[],然后再进行相应操作即可!
这道题我写了四次,用了不同的方法,区别其实也不大,只是写法的问题!这个题其实只要是选择使用了bfs的话,没什么细节问题的话,都是能AC的,不过用时有些不同!
第一种是最快的,是用的数组写的队列!
下面是我写的四份代码:
#include<stdio.h>
#include<string.h>
int t,len,sx,sy,lx,ly;
int vis[315][315];
int xx[8]= {1,1,-2,-2,2,2,-1,-1};
int yy[8]= {-2,2,1,-1,1,-1,2,-2};
struct Node
{
int x,y,step;
}knight[201314];
int knight_moves(int n)
{
Node dangqi;
Node change;
int first=0,last=1;
//头.尾!
knight[0].x=sx;
knight[0].y=sy;
knight[0].step=0;
memset(vis,0,sizeof(vis));
while(last>first)
{
dangqi=knight[first++];//此处为出队!
if(dangqi.x==lx&&dangqi.y==ly)
return dangqi.step;
else
{
for(int i=0;i<8;i++)
{
int X=dangqi.x+xx[i];
int Y=dangqi.y+yy[i];
if(X>=0&&X<n&&Y>=0&&Y<n&&vis[X][Y]==0)
{
vis[X][Y]=1;
change.x=X;
change.y=Y;
change.step=dangqi.step+1;//棋子移动一次,步数step就加一次!
knight[last++]=change;//入队!
}
}
}
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
scanf("%d",&len);
scanf("%d%d",&sx,&sy);
scanf("%d%d",&lx,&ly);
int ans=knight_moves(len);
printf("%d\n",ans);
}
return 0;
}
第二种:用的STL模板写的!
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
int len,sx,dx,sy,dy;
bool vis[315][315];
int xx[8]={1,1,-2,-2,2,2,-1,-1};
int yy[8]={-2,2,1,-1,1,-1,2,-2};
struct horse
{
int x,y,step;
}now;
void knight_moves(int n)
{
queue<horse>Q;
memset(vis,false,sizeof(vis));
now.x=sx,now.y=sy,now.step=0;
Q.push(now);
while(!Q.empty())
{
horse u=Q.front();
Q.pop();
if(u.x==dx&&u.y==dy)
{
cout<<u.step<<endl;
return ;
}
for(int i=0;i<8;i++)
{
int X=xx[i]+u.x;
int Y=yy[i]+u.y;
if(!vis[X][Y]&&X>=0&&X<n&&Y>=0&&Y<n)
{
vis[X][Y]=true;
horse v;
v.x=X,v.y=Y,v.step=u.step+1;
Q.push(v);
}
}
}
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>len>>sx>>sy>>dx>>dy;
knight_moves(len);
}
return 0;
}
第三种:
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
int len,sx,dx,sy,dy;
bool vis[315][315];
int step[315][315];
int xx[8]={1,1,-2,-2,2,2,-1,-1};
int yy[8]={-2,2,1,-1,1,-1,2,-2};
void knight_moves(int n)
{
queue<int>Q;
memset(vis,false,sizeof(vis));
memset(step,0,sizeof(step));
Q.push(sx);
Q.push(sy);
while(!Q.empty())
{
int x=Q.front();
Q.pop();
int y=Q.front();
Q.pop();
if(x==dx&&y==dy)
{
printf("%d\n",step[x][y]);
return ;
}
for(int i=0;i<8;i++)
{
int X=xx[i]+x;
int Y=yy[i]+y;
if(!vis[X][Y]&&X>=0&&X<n&&Y>=0&&Y<n)
{
vis[X][Y]=true;
step[X][Y]=step[x][y]+1;
Q.push(X);
Q.push(Y);
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&len);
scanf("%d%d",&sx,&sy);
scanf("%d%d",&dx,&dy);
knight_moves(len);
}
return 0;
}
第四种:
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
int len,sx,dx,sy,dy;
bool vis[315][315];
int step[315][315];
int xx[8]={1,1,-2,-2,2,2,-1,-1};
int yy[8]={-2,2,1,-1,1,-1,2,-2};
void knight_moves(int n)
{
queue<int>Qx;
queue<int>Qy;
memset(vis,false,sizeof(vis));
memset(step,0,sizeof(step));
Qx.push(sx);
Qy.push(sy);
while(!Qx.empty())
{
int x=Qx.front();
Qx.pop();
int y=Qy.front();
Qy.pop();
//vis[x][y]=false;
if(x==dx&&y==dy)
{
printf("%d\n",step[x][y]);
return ;
}
for(int i=0;i<8;i++)
{
int X=xx[i]+x;
int Y=yy[i]+y;
if(!vis[X][Y]&&X>=0&&X<n&&Y>=0&&Y<n)
{
vis[X][Y]=true;
step[X][Y]=step[x][y]+1;
Qx.push(X);
Qy.push(Y);
}
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&len);
scanf("%d%d",&sx,&sy);
scanf("%d%d",&dx,&dy);
knight_moves(len);
}
return 0;
}