题目链接:
思路
典型的BFS题目。
BFS 全称是 Breadth First Search,中文名是宽度优先搜索,也叫广度优先搜索。
所谓宽度优先。就是每次都尝试访问同一层的节点。 如果同一层都访问完了,再访问下一层。
这样做的结果是,BFS 算法找到的路径是从起点开始的 最短 合法路径。换言之,这条路径所包含的边数最小
首先我们构建一个队列(就是我们要处理的点放在一起,用结构体储存位置和步数),第一个放进去的点自然是我们的起点,然后我们从起点开始,把起点下一步可以走的点全部放入队列,然后把点标记为已经走过,不用再走。然后就重复取点,标记操作,直到队列没有新的点。
代码如下
#include <stdio.h>
#include <string.h>
struct node {
int x, y, step;
} que[444 * 444];
int x_0, y_0;
int vis[555][555];//判断是否踩过
int pa[555][555];//记录最少步数;
int n, m;
int ne[8][2] = {-2, -1, -2, 1, -1, -2, -1, 2, 1, -2, 1, 2, 2, -1, 2, 1}; //马的8个方向
void bfs() {
int i, j, head = 0;
int tail = -1;
que[++tail].x = x_0;//添加进入第一个点
que[tail].y = y_0;
que[tail].step = 0;
while (tail >= head) {//检查是否有新的点
struct node temp = que[head++];
for (i = 0; i < 8; i++) {//遍历八个可以去的点
int tx = temp.x + ne[i][0];
int ty = temp.y + ne[i][1];
if (vis[tx][ty] || tx < 1 || tx > n || ty < 1 || ty > m)//如果不符合条件就跳过
continue;
que[++tail].x = tx;//将符合的点添加进入队列
que[tail].y = ty;
que[tail].step = temp.step + 1;
vis[tx][ty] = 1;//标记此点已经踩过,不用再踩
pa[tx][ty] = que[tail].step;
}
}
}
int main() {
int i, j;
memset(vis, 0, 555 * 555);
memset(pa, -1, 555 * 555);
scanf("%d%d%d%d", &n, &m, &x_0, &y_0);
vis[x_0][y_0] = 1;
pa[x_0][y_0] = 0;
bfs();
for (i = 1; i <= n; i++) {
for (j = 1; j <= m; j++) {
if (j != m)
printf("%-5d", pa[i][j]);
else
printf("%d\n", pa[i][j]);
}
}
}