写在前面
这是蒟蒻第一篇题解。作为一名没带脑子的初中生的第一篇题解,本题解必定存在诸多错误,给您带来的不便敬请谅解。对于不足之处与错误,还请多多包涵,并欢迎批评指正!
本题目来自于洛谷,网址https://www.luogu.com.cn/problem/P1443。
非营利性,侵权请联系删除。
题目详情
马的遍历
题目描述
有一个 $n \times m$ 的棋盘,在某个点 $(x, y)$ 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 $n, m, x, y$。
输出格式
一个 $n \times m$ 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 $-1$)。
样例 #1
样例输入 #1
3 3 1 1
样例输出 #1
0 3 2
3 -1 1
2 1 4
提示
数据规模与约定
对于全部的测试点,保证 $1 \leq x \leq n \leq 400$,$1 \leq y \leq m \leq 400$。
题目解析
基本信息很长,但中心不多。有用的部分无非就是马每次可以到达8个点!
得到这个,我们很自然地就能想到用BFS(广度优先搜索)解决。
广搜的概念就不展示了,感兴趣的读者可以自己查一下 (话说如果不知道啥是广搜再看下去好像也没啥意义了)
怎么搜呢?
从能到达的8个点开始,每个点再向外延伸8个点,统计个数即可。
代码与讲解
开始准备工作:
int path_num[410][410];//存储各点路径数
int x_next[8]={1,2,2,1,-1,-2,-2,-1};//表示“马”可一步到达的点的横坐标
int y_next[8]={2,1,-1,-2,-2,-1,1,2};//表示“马”可一步到达的点的纵坐标
int n,m,x,y;//意义见题意
用结构体存储坐标:
struct dot//表示坐标
{
int nx;//横坐标
int ny;//纵坐标
}k,frt;//k表示待处理点,frt表示待处理点的上一个点
搜索开始:
void bfs(int tx,int ty)//tx,ty分别表示“马”此时坐标
{
path_num[x][y]=0;//对“马”坐标初始化
k.nx=x;
k.ny=y;
queue<dot>q;
q.push(k);//将“马”的坐标传入队列
while(!q.empty())//当前层级没有计算完
{
frt=q.front();//一个一个计算
q.pop();//代表该元素已完成计算
for(int i=0;i<8;i++)//可直接到达的8个点
{
int frt_next_x=frt.nx+x_next[i];//第i个点的横坐标
int frt_next_y=frt.ny+y_next[i];//第i个点的纵坐标
if(path_num[frt_next_x][frt_next_y]==-1&&frt_next_x>=1&&frt_next_x<=n&&frt_next_y>=1&&frt_next_y<=m)//该点没有超出棋盘边界且未计算过
{
k.nx=frt_next_x;//记录新点横坐标
k.ny=frt_next_y;//记录新点纵坐标
path_num[k.nx][k.ny]=path_num[frt.nx][frt.ny]+1;//新点路径数=原来点路径数+1
q.push(k);//将新点存入队列,以进行下一次运算
}
}
}
}
主函数:
int main()
{
cin>>n>>m>>x>>y;
memset(path_num,-1,sizeof(path_num));//默认均无法到达
bfs(x,y);//搜索
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cout<<left<<setw(5)<<path_num[i][j];//按格式输出
cout<<endl;
}
}
全部代码
#include<bits/stdc++.h>
using namespace std;
int path_num[410][410];
int x_next[8]={1,2,2,1,-1,-2,-2,-1};
int y_next[8]={2,1,-1,-2,-2,-1,1,2};
int n,m,x,y;
struct dot
{
int nx;
int ny;
}k,frt;
void bfs(int tx,int ty)
{
path_num[x][y]=0;
k.nx=x;
k.ny=y;
queue<dot>q;
q.push(k);
while(!q.empty())
{
frt=q.front();
q.pop();
for(int i=0;i<8;i++)
{
int frt_next_x=frt.nx+x_next[i];
int frt_next_y=frt.ny+y_next[i];
if(path_num[frt_next_x][frt_next_y]==-1&&frt_next_x>=1&&frt_next_x<=n&&frt_next_y>=1&&frt_next_y<=m)
{
k.nx=frt_next_x;
k.ny=frt_next_y;
path_num[k.nx][k.ny]=path_num[frt.nx][frt.ny]+1;
q.push(k);
}
}
}
}
int main()
{
cin>>n>>m>>x>>y;
memset(path_num,-1,sizeof(path_num));
bfs(x,y);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
cout<<left<<setw(5)<<path_num[i][j];
cout<<endl;
}
}
请注意:
变量有些多,有些变量纯粹为了省事 (少打字) ,一定注意区分!
一定要给数组path_num
赋好初值
其实这道题稍微分析一下还是挺简单的>_<
时间复杂度分析
题目数据最大值是400,因此最多可能循环160000次
由于广搜是以空间换时间,因此时间复杂度相对较低,而空间复杂度则明显要高出不少
以下是洛谷运行结果:
写在最后
第一篇题解,质量不会高。
写了将近三个小时,还请体谅一下。
最后,再次声明:
本题解必定存在诸多错误,给您带来的不便敬请谅解。对于不足之处与错误,还请多多包涵,并欢迎批评指正!
本题目来自于洛谷,网址https://www.luogu.com.cn/problem/P1443。
非营利性,侵权请联系删除。