洛谷 /P1443 马的遍历

164 阅读3分钟

题目描述

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

输入格式

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

输出格式

一个 n \times mn×m 的矩阵,代表马到达某个点最少要走几步(左对齐,宽 55 格,不能到达则输出 -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,起点(x,y)为0,然后开始bfs搜索,每进入一层,深度加一,该深度即步数,这一层的扩展点都是这个步数,一直到队列里没有元素了,整个二维数组就处理完毕,安装要求输出即可。

代码如下(注意点已经注释)

#include<stdio.h>
#include<string.h>
int n,m;
int mp[410][410];//棋盘
int book[410][410];//标记是否走过
//学到了新招就是自定义check函数检查有没有越界
//而且以越界条件先判断好像可以节省时间
//(因为只要一个条件不满足就是越界了)
//就不需要一个一个判断不越界的条件是否满足
int check(int x,int y)
{
    if(x<1||x>n||y<1||y>m)//注意噢x>n和y<m,不要都写成n啦,棋盘范围是n*m而不是n*n
        return 0;
    return 1;//返回1或0是方便后面if条件判断
}
/*最开始下意识以为只有四个方向,定义的
数组是next[4][2],后来改的时候不记得改成
8,答案奇怪的离谱,找了半天(真的找了
久呜呜)居然是这里的问题,麻了麻了.....

int next[8][2]= {{2,1}, //下右日
    {2,-1},//下左日
    {-2,1},//上右日
    {-2,-1},//上左日
    {1,2},//右下日
    {-1,2},//右上日
    {1,-2},//左下日
    {-1,-2}
};//左上日
struct queue//因为是bfs,要用到队列结构体
{
    int x;
    int y;
} que[160001];//范围一定要大于400*400
void bfs(int x,int y)//注意是广度优先搜索哦
{
    int head=0,tail=1;
    int sum=0;//步数清零
    //初始点入队
    que[1].x=x;
    que[1].y=y;
    //标记初始点
    book[x][y]=1;
    mp[x][y]=0;
    while(head<tail)
    {
        head++;
        sum=mp[que[head].x][que[head].y]+1;//后面扩展成功的点深度都加一

        for(int i=0; i<8; i++)//从该点往每个方向遍历
        {
            int ax=que[head].x+next[i][0];
            int ay=que[head].y+next[i][1];
            if(check(ax,ay)&&book[ax][ay] == 0)//如果未到达过,将其入队
            {
                tail++;
                que[tail].x=ax;
                que[tail].y=ay;
                book[ax][ay]=1;
                mp[ax][ay]=sum;//符合要求的点步数都等于sum
            }
            //如果没进入if判断语句说该点不符合要求,通过for循环扩展下一个点即可
        }
    }
}
int main()
{
    int x,y;
    scanf("%d %d %d %d",&n,&m,&x,&y);
    memset(mp,-1,sizeof(mp));//全部初始化为-1
    bfs(x,y);
    //输出结果罢了
    for(int i=1; i<=n; i++)
    {
        for(int j=1; j<=m; j++)
        {
            printf("%-5d",mp[i][j]);//一定一定一定一定一定不要再d后面下意识加了空格!!!血的教训呜呜呜
        }
        if(i!=n)
            printf("\n");
    }
    return 0;
}