这道题只要求输入最小步数即可,而且数据的个数较大,所以优先采用BFS(广度优先搜索):
广度优先搜索,即以数据搜索的广度优先,换句话说就是每一次操作都将所有可能的结果存储下来,随后对数据进行下一步处理,注意是对每组数据都只进行一次处理,如果是一条路走到头,这就变成了深度优先搜索(DFS)。
而基于这个原理,我们可以用队列来处理每一次操作所产生的可能结果,并对数据进行下一步处理,符合队列先进先出(FIFO)的特点。
#include<queue>//引入队列的头文件queue
template <class T, class Container = deque<T> > class queue;//queue的定义
可以看到队列的实现有赖于deque,deque即双端队列,队列只有一端负责输入,另一端负责输出,而双端队列允许从两端写入读出数据。
下面我们定义一个队列,并将其内部数据类型设为pair<int ,int>来存储其坐标
queue<pair<int, int>> q;
此外,像DFS一样,我们要防止遍历回到之前的已经遍历过的点(虽然DFS有回溯操作,但这两者并不是一回事)从而造成死循环,所以我们要定义一个bool类型的数组,用来记录每个坐标是否被访问过。
bool isvis[405][405];
再根据题意,因为马走的是日字形(不同于走迷宫的一步一步,再加上题目强调了是在棋盘上,所以并没有歧义),所以我们要定义一个数组来表示马的所有可能走向,并在循环中对当前马所在的坐标进行遍历操作。
int d[8][2] = { {1,-2},{1,2},{2,-1},{2,1},{-1,2},{-1,-2},{-2,1},{-2,-1} };//注意不要搞错了,做到不重不漏
这时还有个重要的问题,如何表示当前的遍历深度,即如何输出当前马走了多少步。我之前尝试了用一个变量来表示其所遍历的深度,但一直都存在逻辑问题,后来在题解中看到别人用数组来存储遍历深度,即当前节点的深度等于上一个节点的深度加1,后来我想了一下,这其实是一种递归的思想,可以套用到一些其他的BFS题目中,下面是我学习到的表示深度的解法:
int v_nex[405][405];
v_nex[n_x - 1][n_y - 1] = v_nex[temp.first - 1][temp.second - 1] + 1;
这样所有的准备工作都已经基本完成,下面我们将实现该部分的核心代码:
while (!q.empty()) {//empty()是队列中的内置函数,用来判断队列是否为空,如果为空,则返回
temp = q.front();
q.pop();
for (int i = 0; i < 8; i++) {
n_x = temp.first + d[i][0];
n_y = temp.second + d[i][1];
if (n_x<1 || n_x>n || n_y<1 || n_y>m) {
continue;
}
if (isvis[n_x - 1][n_y - 1]) {
continue;
}
q.push({ n_x,n_y });
isvis[n_x - 1][n_y - 1] = 1;
v_nex[n_x - 1][n_y - 1] = v_nex[temp.first - 1][temp.second - 1] + 1;
}
}
因为题目要求输出矩阵内所有的点,所以我们输出是要用for的嵌套循环来输出所有点的深度(即它所需的最少步数)。
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++){
if (i == sta_x && j == sta_y) {
cout << 0 << ' ';
continue;
}
if (v_nex[i - 1][j - 1] == 0) {
cout << -1 << ' ';
continue;
}
cout << v_nex[i - 1][j - 1] << ' ';
}
cout << endl;
}
为了满足题意,我们还要对特值进行if判断加以输出。
接下来还要说明为什么BFS输出的一定是最小值,因为在前文中特意强调了BFS的一个特性,即每次对可能的节点只进行一次操作,不像DFS一样一条路走到头,在所有情况都只进行一次操作的前提下,先出来的答案必然是最小值,所以BFS一般用来解决最小值问题。
下面是完整代码:
#include<queue>
#include<iostream>
#include<cstring>
using namespace std;
queue<pair<int, int>> q;
int n, m, sta_x, sta_y, n_x, n_y;
int v_nex[405][405];
int d[8][2] = { {1,-2},{1,2},{2,-1},{2,1},{-1,2},{-1,-2},{-2,1},{-2,-1} };
pair<int, int> temp;
bool isvis[405][405];
int main(void) {
cin >> n >> m >> sta_x >> sta_y;
q.push({ sta_x,sta_y });
memset(isvis, 0, sizeof isvis);
isvis[sta_x - 1][sta_y - 1] = 1;
while (!q.empty()) {
temp = q.front();
q.pop();
for (int i = 0; i < 8; i++) {
n_x = temp.first + d[i][0];
n_y = temp.second + d[i][1];
if (n_x<1 || n_x>n || n_y<1 || n_y>m) {
continue;
}
if (isvis[n_x - 1][n_y - 1]) {
continue;
}
q.push({ n_x,n_y });
isvis[n_x - 1][n_y - 1] = 1;
v_nex[n_x - 1][n_y - 1] = v_nex[temp.first - 1][temp.second - 1] + 1;
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++){
if (i == sta_x && j == sta_y) {
cout << 0 << ' ';
continue;
}
if (v_nex[i - 1][j - 1] == 0) {
cout << -1 << ' ';
continue;
}
cout << v_nex[i - 1][j - 1] << ' ';
}
cout << endl;
}
return 0;
}
标签:洛谷,P1443,temp,int,BFS,405,nex,sta,isvis
From: https://blog.51cto.com/u_16271511/8634745