总结:这类题大部分都能转化成坐标的型设计进行遍历搜索,都有套路
题意:已知国际象棋中骑士的走法(具体看原图)。现给定棋盘大小与起始位置,问一个骑士从起点走到终点,至少要走几步。
思路:BFS。由于问的是最少步数,而且又是棋盘遍历题,所以优先考虑BFS。对于一个点,扫描其8个方向,若该方向上的下一个点未走过,则将该点入队,标记。最后就是检验一下终点的步数即可。由于是广度优先,所以第一次找到终点时的步数一定是最小的。
代码:
#include<iostream>
#include<queue>
using namespace std;
struct point{
#include<queue>
using namespace std;
struct point{
int x;
int y;
int move;
};
queue<point>q;
int e_x,e_y,l;
int map[400][400];
int dir[8][2]={{-2,-1},{-2,1},{-1,2},{-1,-2},{2,1},{2,-1},{1,2},{1,-2}};
int main()
{
int bfs(point s);
int n,i,j,ans;
int s_x,s_y;
point start;
cin>>n;
while(n--)
{
cin>>l;//l是正方形的边长
cin>>s_x>>s_y>>e_x>>e_y;//起始坐标的输入
for(i=0;i<l;i++)
for(j=0;j<l;j++)
map[i][j]=0;//访问控制,未被访问过的都赋值为零
while(!q.empty())
q.pop();
start.x=s_x;
start.y=s_y;
start.move=0;
ans=bfs(start);
cout<<ans;
int y;
int move;
};
queue<point>q;
int e_x,e_y,l;
int map[400][400];
int dir[8][2]={{-2,-1},{-2,1},{-1,2},{-1,-2},{2,1},{2,-1},{1,2},{1,-2}};
int main()
{
int bfs(point s);
int n,i,j,ans;
int s_x,s_y;
point start;
cin>>n;
while(n--)
{
cin>>l;//l是正方形的边长
cin>>s_x>>s_y>>e_x>>e_y;//起始坐标的输入
for(i=0;i<l;i++)
for(j=0;j<l;j++)
map[i][j]=0;//访问控制,未被访问过的都赋值为零
while(!q.empty())
q.pop();
start.x=s_x;
start.y=s_y;
start.move=0;
ans=bfs(start);
cout<<ans;
}
return 0;
}
int bfs(point s)
{
int i;
map[s.x][s.y]=1;
point m,n;
q.push(s);
while(!q.empty())
{
m=q.front();//将前一对象的值传递
q.pop();//移除队首元素
if(m.x==s.x&&m.y==s.y) return m.move;
for(i=0;i<8;i++)
{
int x=m.x+dir[i][0];
int y=m.y+dir[i][1];//一次循环移动一个坐标
if(x>=0&&x<l&&y>=0&&y<l&&!map[x][y])
{
map[x][y]=1;
n.x=x;
n.y=y;
n.move=m.move+1;
q.push(n);
}
}
}
}
return 0;
}
int bfs(point s)
{
int i;
map[s.x][s.y]=1;
point m,n;
q.push(s);
while(!q.empty())
{
m=q.front();//将前一对象的值传递
q.pop();//移除队首元素
if(m.x==s.x&&m.y==s.y) return m.move;
for(i=0;i<8;i++)
{
int x=m.x+dir[i][0];
int y=m.y+dir[i][1];//一次循环移动一个坐标
if(x>=0&&x<l&&y>=0&&y<l&&!map[x][y])
{
map[x][y]=1;
n.x=x;
n.y=y;
n.move=m.move+1;
q.push(n);
}
}
}
}