洛谷 P1443 马的遍历

题目描述

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

输入格式

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

输出格式

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

输入输出样例

输入 #1

3 3 1 1

输出 #1

0    3    2    
3    -1   1    
2    1    4    

说明/提示

数据规模与约定

对于全部的测试点,保证 1≤x≤n≤400,1≤y≤m≤400。

题解

 一道很水的bfs,直接求最短路就行,思路跟血色先锋队很像(实际上大部分bfs求最短路都一样)可以去看我前面的题解,再去做一下:洛谷 P1332 血色先锋队-CSDN博客

这道题有两个细节需要注意,一个是输出格式,是要后缀补足5个空;第二个则是输出-1。

当然这两个都是可以通过特判做得,但是有点麻烦,这里给大家普及一个小知识。

/*读入三个整数,按每个整数占8个字符的宽度,右对齐输出它们,按照格式要求依次输出三个整数,之间以一个空格分开。*/

上面这道题要求每个数字都占8个字符,有两种做法:

1.用c++函数库

在头文件<iomanip>中有一个函数setw(),setw(x)表示给后面的数补足x位,比如:

cout<<setw(3)<<1;输出  1

而且有一个地方需要注意,就是setw函数默认给后面补足,如:

cout<<1<<setw(3)<<44;输出1 44

2.用printf输出

用printf输出一个整数是printf("%d",a);

而想要在前面补空格则是printf("%5d",a);表示在a前面补足5位(不够补空格)

想要在后面补空格则是在数字前面加一个-,想想,%5d表示在前面补足5位,那么%-5d不就是在后面了吗?

还有一个是在5之前加个0,则是在前面补零,如a=1;printf("%05d",a);输出00001

知道了这些,这题就简单了,直接上代码:

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define ll long long
using namespace std;
int n,m,x1,y1;
int a[405][405];
int vis[405][405];
//a存储答案,vis标记 
struct node{
	int x,y;
}; 
queue<node>q;
int dx[10]={0,-2,-2,-1,-1,1,1,2,2};
int dy[10]={0,-1,1,-2,2,-2,2,-1,1};
//8个可跳的位置 
void bfs(){
	node h;h.x=x1,h.y=y1;
	q.push(h),vis[x1][y1]=1;
	while(!q.empty()){
		node h=q.front();
		q.pop(); 
		int x1=h.x,y1=h.y;
		for(int i=1;i<=8;i++){
			for(int j=1;j<=8;j++){
				int x2=x1+dx[i],y2=y1+dy[i];
				if(!vis[x2][y2]&&x2>=1&&x2<=n&&y2>=1&&y2<=m){
					vis[x2][y2]=1;
					a[x2][y2]=a[x1][y1]+1;
					h.x=x2,h.y=y2;
					q.push(h);
				}
			}
		}
	}
}//bfs模板,不会的看血色先锋队,这里就不多说了 
int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	scanf("%d%d%d%d",&n,&m,&x1,&y1);
	memset(a,-1,sizeof(a)),a[x1][y1]=0;
	//全部赋值-1,输出时比较方便,同时马的位置应是0 
	bfs();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			printf("%-5d",a[i][j]);
		}cout<<endl;
	}
    return 0;
    //fclose(stdin);
	//fclose(stdout);
}


AC快乐

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值