P1443 马的遍历

题目描述

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

输入格式

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

输出格式

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

输入输出样例

输入 #1复制

3 3 1 1

输出 #1复制

0    3    2    
3    -1   1    
2    1    4    

说明/提示

数据规模与约定

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

 1.这个题目刚开始看一脸懵逼,因为我看样例觉得很奇怪(我不会走象棋,所以没有往那方面去思考),我好奇去搜了一下象棋中马的走法,我才知道,原来马是横着走一格加上斜着走一格。所以马可以这么走:

 这其实变相是一个迷宫问题,此题求的是最短路径,所以我们用bfs来解决

2.这里其实只是方位变了而已,bfs的思想就是在head点上延生所有的可能到tail的点上,在此过程中,head会往后走,所以tail走过的值,head也会在那里继续延生。

3.我们也要判断走的这8个方位是否越界,是否走过,同时我们需要在数组中记录路径。

代码如下:

#include<stdio.h>//马是直走一格斜着走一格
#define N 410
#define M 410
struct node
{
	int x;
	int y;
	int s;	
}a[N*M];
int head,tail,book[N][M],king[N][M];
int n,m,x,y;
int dfs()
{
	int i,j,tx,ty;
	book[x][y]=1;
	a[tail].x=x;
	a[tail].y=y;
	a[tail].s=0;
	tail++;
	int k[8][2]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2}};
	while(head<tail)
	{
		for(i=0;i<8;i++)
		{
			tx=a[head].x+k[i][0];
			ty=a[head].y+k[i][1];
			if(tx>0&&tx<=n&&ty>0&&ty<=m)
			{
				if(book[tx][ty]==0)
				{
					a[tail].x=tx;
					a[tail].y=ty;
					a[tail].s=a[head].s+1;
					book[tx][ty]=1;	
					king[tx][ty]=a[tail].s;
					tail++;
				}
			}
		}
		head++;
	}
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=m;j++)
		{
			if(king[i][j]==0&&i!=x&&j!=y) king[i][j]=-1;
		}
	}
}
int main()
{
	int i,j;
	scanf("%d%d%d%d",&n,&m,&x,&y);
	dfs();
	for(i=1;i<=n;i++)
	{
		for(j=1;j<=m;j++)
		{
			printf("%-5d",king[i][j]);
		}
		printf("\n");
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值