问题描述:
我们知道,马的走法都是日字。现在假设马在无穷大的棋盘上的(x,y)处,那么下一步它可以走到的点为(x±1,y±2)或(x±2, y±1)。
现在给定初始的马在(0,0)处,马要跳到某个(x_final,y_final)点,而棋盘上有一些凹陷点马无法跳到上面。请求出马跳到(x,y)至少几步并输出答案,如果跳不到请输出fail。
注意每一步就指跳一个日字,而不是移动一格。不考虑中国象棋中的挡马脚规则。
输入:
马要跳到的坐标x_final、y_final
凹陷点数目n
凹陷点坐标
x1 y1
...
xn yn
终点坐标和凹陷点坐标都在(-100, -100)到(100, 100)为对角线的正方形内
输出:
马最少跳的步数
如果跳不到输出fail
样例输入输出:
3 5
4
2 1
1 2
0 3
-1 3
out:
4
这个其实就是一共广度优先遍历,但是不用图来实现,因为太复杂了。棋盘可以看作是一共n^2个顶点的图,每个点和马走的八个方向的点有无向边,起始顶点在(0,0) 。有一些缺陷点,在图中把这些顶点以及相邻的边删除掉就可以了。
可以用一共二维数组记录棋盘,默认是0,走过的即为1,缺陷的记为3;目标点记为2
然后基于广度优先搜索的思想,用一共队列,存目前遍历点八个方向遍历到的点,取出这个点的时候再在八个方向进行搜索。如果前进需要满足2个条件:此点在棋盘内;此点在之前没有遍历过且无凹陷;
代码实现:
#include<iostream>
#include<stdio.h>
#include<queue>
using namespace std;
int cmap[201][201]; //棋盘记录,默认是0,走过的即为1,缺陷的记为3;目标点记为2
int dir[8][2]={{-1,-2},{-2,-1},{-1,2},{-2,1},{1,-2},{2,-1},{1,2},{2,1}};//八个方向
/*
用BFS的方式进行遍历,每个点可以往8个方向前进
如果前进需要满足2个条件:此点在棋盘内;此点在之前没有遍历过且无凹陷(==0);
利用数组储存地图以及行走过的点。
*/
int bfs_horsemove()
{
queue<int>qrow,qclu,qstep; //广度优先搜索,辅助队列qxxx,
qrow.push(100);
qclu.push(100);
qstep.push(0);
while(!qrow.empty()) //每次走完八步,进一次while循环
{ //其中,走到未经过点、都会加入下一步队列 qxxx
int nowrow=qrow.front();
qrow.pop();
int nowclu=qclu.front();
qclu.pop();
int nowstep=qstep.front();
qstep.pop();
for(int i=0;i<8;++i){
int nextrow=nowrow+dir[i][0];
int nextclu=nowclu+dir[i][1];
int nextstep=nowstep+1;
if(nextrow>=0&&nextrow<200&&nextclu>=0&&nextclu<200){
if(cmap[nextrow][nextclu]==2) //找到目标,由于是一步一步走的(八个方向循环过一次)
return nextstep; //第一次找到目标,一定是最短路劲
if(cmap[nextrow][nextclu]==0){ //在不超过边界且为到过的点、部位凹陷,则进入队列
qrow.push(nextrow);
qclu.push(nextclu);
qstep.push(nextstep);
cmap[nextrow][nextclu]=1;
}
}
}
}
}
int main()
{
int a,b;
cin>>a>>b;
int n;
cin>>n;
int umbilic,umbilir; //缺陷点坐标记录
for (int i=0;i<n;i++)
{
cin>>umbilir>>umbilic;
cmap[umbilir+100][umbilic+100]=3;
}
cmap[a+100][b+100]=2;
int ans=bfs_horsemove();
cout<<ans<<endl;
cin>>n;
return 0;
}
这里输入点+100才是原点(0,0),因为点坐标范围都在-100~100,所以棋盘设了201^2个点的大小,现在仔细想想可能是少考虑了一些情况。参考的同学可以把棋盘扩大试试。
算法存在一些没考虑到的点,在OJ中有一个WRONG ANSWER,如果有参考这篇代码把wrong answer解决了的同学,可以私信我或评论一下,感激不尽。
ps:这个代码是jqs老师2021-2022秋季学期数据结构课程OJ作业,如果看到有一样的代码是我本人写的,不是抄袭,老师助教明察。同学们理性参考。
参考博客:
优快云:BFS 搜索 Problem 1015 Knight Moves "马走日"之最少步数