写在前面

这是蒟蒻第一篇题解。作为一名没带脑子的初中生的第一篇题解,本题解必定存在诸多错误,给您带来的不便敬请谅解。对于不足之处与错误,还请多多包涵,并欢迎批评指正!
本题目来自于洛谷,网址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。
非营利性,侵权请联系删除。

THE END~

posted on 2023-07-09 22:38  httony  阅读(242)  评论(2编辑  收藏  举报