洛谷-马的遍历

164 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情

马的遍历

题目描述

有一个 n×mn \times m 的棋盘,在某个点 (x,y)(x, y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。

输入格式

输入只有一行四个整数,分别为 n,m,x,yn, m, x, y

输出格式

一个 n×mn \times m 的矩阵,代表马到达某个点最少要走几步(不能到达则输出 1-1)。

样例 #1

样例输入 #1

3 3 1 1

样例输出 #1

0    3    2    
3    -1   1    
2    1    4

提示

数据规模与约定

对于全部的测试点,保证 1xn4001 \leq x \leq n \leq 4001ym4001 \leq y \leq m \leq 400

分析

这是一道最短路类型的BFSBFS,用队列可以写出来,就是先将cntcnt数组赋值成-1,然后从马的位置开始向八个方向遍历,注意啦,马走日象走田,所以有八个方向,最后把整个cntcnt的二维数组输出就行啦。

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string> 
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack> 
#include <cmath>
#include <iomanip>
#define ll long long
#define AC return
#define Please 0
using namespace std;
const int N=410;
const double esp=1e-8;
typedef pair<int,int>PII;
typedef unsigned long long ull; 
int n,m,x,y;
inline int read(){//快读 
    int x=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0' && ch<='9'){
        x=x*10+ch-'0'; 
        ch=getchar();
    }
    AC x*f;
}
bool st[N][N];
int cnt[N][N];
int dx[8]={1,2,2,1,-1,-2,-2,-1};
int dy[8]={2,-1,1,-2,-2,-1,1,2};
bool check(int x,int y){
	return (x>=1 && x<=n && y>=1 && y<=m);
}
inline void bfs(int s,int t){
	queue<PII>q;
	q.push({s,t});
	cnt[s][t]=0;
	st[s][t]=1;
	while(q.size()){
		PII t=q.front();
		q.pop();
		int nowx=t.first,nowy=t.second;
		for(int i=0;i<8;i++){
			int nex=nowx+dx[i],ney=nowy+dy[i];
			if(check(nex,ney) && !st[nex][ney]){
				q.push({nex,ney});
				st[nex][ney]=1;
				cnt[nex][ney]=cnt[nowx][nowy]+1;
			}
		}
	}
}
int main(){
	n=read(),m=read(),x=read(),y=read();
	memset(cnt,-1,sizeof cnt);
	bfs(x,y);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cout<<cnt[i][j]<<" ";
		}
		cout<<endl;
	}
	return 0;
}

希望能帮助到大家(QAQQAQ)!.