马的遍历
题目描述
有一个 n × m n \times m n×m 的棋盘,在某个点 ( x , y ) (x, y) (x,y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n , m , x , y n, m, x, y n,m,x,y。
输出格式
一个 n × m n \times m n×m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 − 1 -1 −1)。
样例 #1
样例输入 #1
3 3 1 1
样例输出 #1
0 3 2
3 -1 1
2 1 4
提示
数据规模与约定
对于全部的测试点,保证 1 ≤ x ≤ n ≤ 400 1 \leq x \leq n \leq 400 1≤x≤n≤400, 1 ≤ y ≤ m ≤ 400 1 \leq y \leq m \leq 400 1≤y≤m≤400。
Code:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXSIZE 2000 //循环队列最大值, 这里有点问题, 建议用链表那种
typedef struct { //坐标结构体
int x, y;
}Pos;
typedef struct { //队列结构体
Pos data[MAXSIZE]; //坐标数组
int front;
int rear;
}Quene;
void InitQuene(Quene *Q){ //初始化队列
Q->front = 0;
Q->rear = 0;
return ;
}
bool QueneEmpty(Quene *Q){ //队列是否为空
if(Q->rear == Q->front)
return true;
return false;
}
bool EnQuene(Quene *Q, Pos p){ //入队
if((Q->rear + 1) % MAXSIZE == Q->front)
return false;
Q->data[Q->rear] = p;
Q->rear = (Q->rear + 1) % MAXSIZE;
return true;
}
bool DeQuene(Quene *Q, Pos *p){ //出队
if(Q->rear == Q->front)
return false;
*p = Q->data[Q->front];
Q->front = (Q->front + 1) % MAXSIZE;
return true;
}
int main(){
int n, m, x0, y0;
scanf("%d %d %d %d", &n, &m, &x0, &y0);
int arr[405][405] = {0}; //存储步数
int dx[] = {1, 1, 2, 2, -1, -1, -2, -2}; //八个方向的走法
int dy[] = {2, -2, 1, -1, 2, -2, 1, -1};
int i, j;
for(i = 1; i <= n; i++){ //初始化为-1 表示没走过 或不可达
for(j = 1; j <= m; j++){
arr[i][j] = -1;
}
}
arr[x0][y0] = 0; //第一个坐标为0步
Quene q; //建立循环队列
InitQuene(&q); //初始化循环队列
Pos p1 = {x0, y0}, p2; //p1入队的坐标 p2坐标的临时存储
EnQuene(&q, p1); //p1入队 广度优先搜索
while(!QueneEmpty(&q)){ //队列非空
DeQuene(&q, &p1); //将队头出列 赋值给p1
int i;
for(i = 0; i < 8; i++){ //搜索没走过的点并步数加1
int x_pos = p1.x + dx[i], y_pos = p1.y + dy[i];
if(x_pos < 1 || x_pos > n || y_pos < 1 || y_pos > m || arr[x_pos][y_pos] != -1) continue;
arr[x_pos][y_pos] = arr[p1.x][p1.y] + 1;
p2.x = x_pos; //临时变量p2赋值
p2.y = y_pos;
EnQuene(&q, p2); //p2 入队
}
}
for(i = 1; i <= n; i++){ //输出
for(j = 1; j <= m; j++){
printf("%d ", arr[i][j]);
}
putchar('\n');
}
return 0;
}