洛谷 普及组 P1443 马的遍历

题目描述

有一个n*m的棋盘,在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步

输入格式

一行四个数据,棋盘的大小和马的坐标

输出格式

一个n*m的矩阵,代表马到达某个点最少要走几步(左对齐,宽5格,不能到达则输出-1)

数据范围

1

输入输出样例

  输入

3 3 1 1

  输出

0    3    2    
3    -1   1    
2    1    4   

思路

典型广搜(BFS)。

▶n行m列的表格相当于棋盘,象棋盘中马虽是在点上走,但也可看作在单元格中移动。象棋中马有8个操作方向,用dir[8][2]数组代表8个方向(可见下图)

▶一般来说,BFS需要用上队列queue,为方便存储单元格位置,使用结构体node来存储某单元格的坐标,入队时传输坐标即可

▶从某点开始,往8个方向查找,只要到达的下个格子在地图上且未访问过,就更新其步数加入队列,此时到达它的步数一定是最少的。直到8个方向操作完,再取队首依然遍历8个方向,找到所能到达的下个格子。重复过程直到能访问到的格子都走一遍。剩下的就是不能到达的格子

▶按顺序输出step数组即可

                                                       

洛谷 普及组 P1443 马的遍历_第1张图片 dir数组表示方向
#include
#include
#include
#include
using namespace std;
int dir[8][2] = { {-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2}};
bool vis[401][401]; //访问数组
int step[401][401]; //计步数组
int n, m;
struct node{
	int dx, dy;
	node(int xx, int yy){dx = xx; dy = yy;}
}; 
queue q;
void bfs(int x, int y)
{
	while(!q.empty()){
		node now = q.front();
		q.pop();
		for(int i = 0; i < 8; i++){
			int nx = now.dx+dir[i][0], ny = now.dy+dir[i][1];
			if(nx>0&&nx<=n&&ny>0&&ny<=m && !vis[nx][ny]){
				vis[nx][ny] = true;
				step[nx][ny] = step[now.dx][now.dy]+1; //原有的步数+1
				q.push(node(nx, ny));
			}
		}
	}
}
int main()
{
	int sx, sy;
	cin >> n >> m >> sx >> sy;
	memset(step, -1, sizeof(step)); //未访问的初始化为-1 
	vis[sx][sy] = 1; //起点标记已访问
	step[sx][sy] = 0;//起点步数为0 
	q.push(node(sx, sy));
	bfs(sx, sy);	 //从起点遍历 
	for(int i = 1; i <= n; i++){
		for(int j = 1; j <= m; j++)
			cout << setiosflags(ios::left) << setw(4) << step[i][j] << " ";
		cout << endl;		
	}
	return 0;	
}

 

你可能感兴趣的:(洛谷刷题日记)