传送门:P1443 马的遍历
题目描述
有一个 n×m 的棋盘,在某个点 (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n,m,x,y。
输出格式
一个 n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 −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)
解题思路
首先初始化ans数组,使其中的值全为-1。在方向数组中,要明白马在象棋中是怎么走的(此处不再介绍),第一次进入bfs时,记得将ans[x][y]设置为0,否则答案会出现错误。剩下的即为常规的BFS。
AC代码
#include<bits/stdc++.h>
using namespace std;
int n, m, x, y;
bool vis[1010][1010];//标记是否走过
int X[8] = { -1,-2,-2,-1,1,2,2,1 };
int Y[8] = { 2,1,-1,-2,2,1,-1,-2 };//8个方向
int ans[500][500];
void bfs()
{
queue<pair<int, int> >q;//一个队列,存放坐标
ans[x][y] = 0;//在(x,y)时走了0步
q.push({ x,y });
vis[x][y] = true;
while (!q.empty())//在队列清空前一直执行该循环
{
pair<int, int> t = q.front();//获取最前面的元素
int a = t.first;//取出队首
int b = t.second;
q.pop();//出队
for (int i = 0; i < 8; i++)//8个方向,所以i<8
{
int u = a + X[i];//每次搜索后更新u,v,即为返回到上一个点
int v = b + Y[i];
if (u<1 || u>n || v<1 || v>m || vis[u][v])//如果出界,或者走过,直接跳过
continue;
vis[u][v] = true;//标记来过
q.push({ u,v });//加入该点到队列中
ans[u][v] = ans[a][b] + 1;//步数等于上一个可能点加1
}
}
}
int main()
{
cin >> n >> m >> x >> y;
memset(ans, -1, sizeof(ans));//初始化
bfs();
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cout << setw(5) << ans[i][j];
}
cout << endl;
}
return 0;
}