BlizzardCan 算法之路
题目描述
有一个 n×m 的棋盘,在某个点 (x, y) 上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步。
输入格式
输入只有一行四个整数,分别为 n, m, x, y。
输出格式
一个 n×m 的矩阵,代表马到达某个点最少要走几步(左对齐,宽 5 格,不能到达则输出 -1)。
输入输出样例
3 3 1 1
0 3 2
3 -1 1
2 1 4
说明/提示
数据规模与约定
对于全部的测试点,保证1≤x≤n≤400,1≤y≤m≤400。
思路
因为马在一个点有多种出发点,则考虑宽搜,理论上dfs也可以做,不过复杂度会更高
其实就是宽搜的板子,多注意下细节
例如 输出宽度为5,若不能达到就输出-1。
AC代码
//
// Created by BlizzardCan on 2021/8/4.
//
// 涉及多种方向 -> bfs
#include<iostream>
#include<cstring>
#include<stdio.h>
#include<queue>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int N =420;
int g[N][N]; // 已经初始化为0
int n,m,x,y;
bool s[N][N]={false};
queue<PII> op;
int dx[4]={1,-1,2,-2},dy[4]={1,-1,2,-2};
void bfs(int x,int y,int res){
g[x][y]=res;
s[x][y]=true;
op.push({x,y});
while(!op.empty()){
PII t=op.front();
op.pop();
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(abs(dx[i])!=abs(dy[j])){
int x1=t.first+dx[i];
int y1=t.second+dy[j];
if(x1<1||x1>n||y1<1||y1>m) continue;
if(!s[x1][y1]){ //如果没在队列内,即没有确定它,则push进队列
op.push({x1,y1});
s[x1][y1]=true;
g[x1][y1]=g[t.first][t.second]+1;
}
}
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
memset(g,-1,sizeof g);
cin>>n>>m>>x>>y;
bfs(x,y,0);
int j;
for(int i=1;i<=n;i++) {
for (j = 1; j <= m; j++)
printf("%-5d", g[i][j]);
printf("\n");
}
}