原题链接:
https://www.luogu.com.cn/problem/P1443
题目描述
有一个 n×m 的棋盘,在某个点 (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n, m, x, y。
输出格式
一个n×m 的矩阵,代表马到达某个点最少要走几步(左对齐,宽 5 格,不能到达则输出 −1)。
输入输出样例:
输入#1
3 3 1 1
输出#1
0 3 2
3 -1 1
2 1 4
提示
数据规模与约定
对于全部的测试点,保证1 ≤ x ≤n ≤ 400,1 ≤ y ≤ m ≤ 400。
思路方法:
这题需要采用广度优先搜索的策略(BFS),先定义一个标记数组,,记录马行走过的点 ,然后定义一个答案数组,记录马到达点的最小步数 ,再定义两个队列,记录可行点的坐标。首先将马的当前位置作为起点,进行标记和记录步数,然后当前点进入队列。然后进入一个二维循环,外层循环判断队列是否为空,内层循环依次遍历马的8个落点(别告诉我马走八方你都不知道🙃),可行的落点进行标记并记录步数,然后可行的点要进入队列中。8个方向判断完后,当前的点需要出栈。最终直到栈为空结束。
AC代码:
#include <bits/stdc++.h>
using namespace std;
int n, m, x, y;
queue<int>q,q1;//分别表示当前的行和列
vector<vector<int> >a(401, vector<int>(401));//标记数组,记录马行走过的点
vector<vector<int> >b(401, vector<int>(401, -1));//答案数组,记录马到达点的最小步数
int dx[8]={-2,-2,2,2,1,-1,1,-1};//压缩马行走的8个方向
int dy[8]={-1,1,-1,1,2,-2,-2,2};
void BFS(){
while(!q.empty()){//队列中有元素就一直循环
for(int i = 0; i < 8; i++){//依次判断马的8个方向是否可走
int xx = q.front() + dx[i];//记录行走后的位置
int yy = q1.front() + dy[i];
if(xx > 0 && xx <= n && yy > 0 && yy <= m && !a[xx][yy]){//判断是否越界,是否被访问过
a[xx][yy] = 1;//标记为访问过
b[xx][yy] = b[q.front()][q1.front()] + 1;//当前的步数记录为前一个点的步数 +1
q.push(xx);//将当前点入队
q1.push(yy);
}
}
q.pop();//当前点的8个方向判断完毕,当前点出队
q1.pop();
}
}
int main(){
cin>>n>>m>>x>>y;
q.push(x);//将当前位置作为起点
q1.push(y);
a[x][y] = 1;//起点标记为走过
b[x][y] = 0;//起点的步数为0
BFS();
for(int i = 1; i <= n; i++){//输出答案
for(int j = 1; j <= m; j++){
printf("%-5d",b[i][j]);
}
printf("\n");
}
return 0;
}