洛谷: P1443 马的遍历
原题地址:P1443 马的遍历 - 洛谷
题目描述
有一个 n×m 的棋盘,在某个点 (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n,m,x,y。
输出格式
一个 n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 −1)。
该题可以用bfs广度优先搜索遍历来解决,因为广度优先遍历可以保证第一次访问某一个节点时得到的结果就是最短路径,完美的符合该题的题意。可以用stl类中的queue容器。即动态扩容的队列,可以有效地避免数组开的过大或过小,而发生错误。并且不能用延迟标记的方法,要立即标记当前的状态。我第一次就是用的延迟标记的方法,但是最后会超出队列的内存限制,再请教了deepseek之后,才了解到了延迟标记和立即标记的具体区别.
这也让我长见识了 。
具体代码如下:
#include <iostream>
#include <queue>
using namespace std;
//每个结构体包含当前点的坐标以及到达该店所需要的步数
struct node{
int a,b,step;
};
int row,col;
int grid[405][405];
//马走日的八个方向
int dict[8][2] = {{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2}};
void bfs(int x,int y){
//queue可以动态的分配内存,否则的话容易栈溢出
queue<node> q;
q.push({x,y,0});
grid[x][y] = 0;
while (!q.empty()){
node qq = q.front();
q.pop();
int xx = qq.a;
int yy = qq.b;
int s = qq.step;
for (int i = 0;i < 8;++i){
int ix = xx + dict[i][0];
int iy = yy + dict[i][1];
if (ix >= 1 && ix <= row && iy >= 1 && iy <= col && grid[ix][iy] == -1)
{
//立刻标记状态,如果使用延迟标记的话会进行重复入队的操作,会超出内存限制
grid[ix][iy] = s + 1;
q.push({ix,iy,s + 1});
}
}
}
}
int main()
{
int x,y;
cin>>row>>col>>x>>y;
for (int i = 1;i <= row;++i){
for (int j = 1;j <= col;++j){
grid[i][j] = -1;
}
}
bfs(x,y);
for (int i = 1;i <= row;++i){
for (int j = 1;j <= col;++j){
printf("%-3d ",grid[i][j]);
}
cout<<endl;
}
return 0;
}