题目连接:https://www.luogu.com.cn/problem/P1443
这道题问的是最少要几步,所以可以用 b f s bfs bfs(广度优先搜索)解决。
初始化
b f s bfs bfs 要用到队列。
队列有两种表示方法:
-
数组: q [ i ] q[i] q[i] 表示队列的第 i i i 项.
head
,tail
指向队头和队尾。 -
queue:先进先出的线性表。
需要头文件
#include<queue>
定义
queue <int> q;
入队
q.push(x);
出队
q.pop();
查询队列中元素个数
q.size()
代码:
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= m;j ++)
map[i][j] = -1; //初始化,答案可能为0
map[x][y] = 0; //马的初始坐标答案为0
head = tail = 1; //队首和队尾初始化
q[head][1] = x; //队首的坐标进队
q[head][2] = y;
增量数组
题目中,马走的是日字形。
如图所示,增量数组为
d x [ ] = { 1 , 2 , 2 , 1 , − 1 , − 2 , − 2 , − 1 } dx[ ] = \{1, 2, 2, 1, -1, -2, -2, -1\} dx[]={1,2,2,1,−1,−2,−2,−1}
d y [ ] = { 2 , 1 , − 1 , − 2 , − 2 , − 1 , 1 , 2 } dy[ ] = \{2,1,-1,-2,-2,-1,1,2\} dy[]={2,1,−1,−2,−2,−1,1,2}。
bfs
while (head <= tail)//如果队列里有数
{
for (int i = 0;i < 8;i ++)
{
int newx = q[head][1] + dx[i];
int newy = q[head][2] + dy[i];
if (newx > n || newx < 1 || newy > m || newy < 1) continue;
//判断是否出界
if (map[newx][newy] >= 0) continue;
//有没有访问过
q[++tail][1] = newx;
q[tail][2] = newy;
//进队
map[newx][newy] = map[q[head][1]][q[head][2]] + 1;
//标记答案
}
head ++;//队头出队
}
输出
题目中要求 左对齐,宽五格
,在c++里的实现方法为printf("%-5d",map[i][j]);
。
完整代码
#include<iostream>
#include<iomanip>
#include<cstdio>
using namespace std;
int n,m,x,y;//n,m表示棋盘的长和宽,x,y表示马的坐标
int map[450][450];//用于存图
int head,tail;//队首和队尾
int q[160050][5];//队列 q[i][1]表示i的x坐标
//q[i][2]表示y坐标
int dx[] = {2,2,1,1,-2,-2,-1,-1};//增量数组
int dy[] = {1,-1,2,-2,1,-1,2,-2};
int main()
{
cin >> n >> m >> x >> y;
for (int i = 1;i <= n;i ++)
for (int j = 1;j <= m;j ++)
map[i][j] = -1;//初始化,答案可能为0
map[x][y] = 0;//马的初始坐标答案为0
head = tail = 1;//队首和队尾初始化
q[head][1] = x;//队首的坐标进队
q[head][2] = y;
while (head <= tail)//如果队列里有数
{
for (int i = 0;i < 8;i ++)
{
int newx = q[head][1] + dx[i];
int newy = q[head][2] + dy[i];
if (newx > n || newx < 1 || newy > m || newy < 1) continue;
//判断是否出界
if (map[newx][newy] >= 0) continue;
//有没有访问过
q[++tail][1] = newx;
q[tail][2] = newy;
//进队
map[newx][newy] = map[q[head][1]][q[head][2]] + 1;
//标记答案
}
head ++;//队头出队
}
for (int i = 1;i <= n;i ++)
{
for (int j = 1;j <= m;j ++)
printf("%-5d",map[i][j]);//输出
cout << endl;
}
}