广度优先搜索(BFS) 马的遍历

题目描述

有一个n*m的棋盘(1<n,m<=400),在某个点上有一个马,要求你计算出马到达棋盘上任意一个点最少要走几步

输入

一行四个数据,棋盘的大小和马的坐标

输出

一个n*m的矩阵,代表马到达某个点最少要走几步(中间的数用空格分开)

样例输入

3 3 1 1

样例输出

0 3 2
3 -1 1
2 1 4

好久没更新博客了,这段时间偷懒在玩游戏,部分学习笔记写了也没有放到博客。主要原因是写博客要排版比较麻烦。今天学习广度优先搜索,碰到了这题,搞了大半天才解决。

思路:
若红点为马,可以往上下左右8个方向走动。
在这里插入图片描述
假设马的位置为(4,4) 那么可以走的位置是
在这里插入图片描述

所以,马的位置定义一个二维数组里,设当前点坐标为(sn,sm),这8个点可以这样来

static int point[][] = {{2,1},{1,2},{2,-1},{1,-2},{-2,-1},{-1,-2},{-1,2},{-2,1}};
for (int i = 0; i < 8; i++) //尝试向八个方向走
{
    int x = sn + point[i][0];
    int y = sm + point[i][1];
    if(check(x,y))  //检查这坐标能不能去
    {
        ....
    }
}

定义棋盘数组chess[][],全部初始化为-1,定义horse()函数从起点开始遍历八个方向可以走的点,加入队列中,(还没接触到java队列数据结构。队列我用了另外一个二维数组queue[][]存放了),再遍历队列里的方向。最后输出结果。

毕竟第一次搞bfs,代码写得还是有点累赘。

import java.util.Scanner;

public class Main {
    static int chess[][]; //定义一个棋盘数组n*m
    static int n,m;     //行与列
    static int sn,sm;   //马的第一个落脚点的xy坐标
    static int point[][] = {{2,1},{1,2},{2,-1},{1,-2},{-2,-1},{-1,-2},{-1,2},{-2,1}};
    //用于指向马的下一步位置,马向8个方向走的坐标
    static int queue[][];   //用二维数组定义一个队列,存放x,y坐标及步数step
    static int front,rear;  //队列头部和尾部指针
    public static void main(String[] args)
    {
    	Scanner in = new Scanner(System.in);
        n = in.nextInt(); m = in.nextInt(); sn = in.nextInt(); sm = in.nextInt();
        chess = new int[n+1][m+1];  //坐标点从1,1开始计算
        queue = new int[n*m][3];    //定义马走过步数的队列,最大入列数为n*m。存放x,y坐标及步数step
        for (int i = 1; i <= n; i++) //将棋盘初始化全为-1
        {
            for (int j = 1; j <= m; j++)
            {
                chess[i][j] = -1;
            }
        }
        chess[sn][sm] = 0;  //马最初点的步数为0
        queue[rear][0] = sn;    //将马最初点装进队列,准备循环
        queue[rear][1] = sm;
        queue[rear][2] = 0;
        rear++; //装进队列后,队列尾移动一位
        do{
            int temp = rear;    //将当前的对尾放入temp,因为horse函数会添加数据导致改变队尾
            for (int i = front; i < temp; i++) {    //有多少个步数一样数据就循环多少次
                horse(queue[i][0],queue[i][1],queue[i][2]); //马在当期坐标尝试向八个方向走,如果可以走就入队列
                front++;    //出队列,头部移动一位
            }
        }while(front != rear);  //当队列头部和尾部相同说明已经完了

        for (int i = 1; i <= n; i++) {  //打印棋盘结果
            for (int j = 1; j <= m; j++) {
                System.out.print(chess[i][j] + " ");
            }
            System.out.println();
        }
    }

    static void horse(int sn, int sm, int step) //马在当期坐标(sn,sm)尝试向八个方向走,如果可以走就入队列
    {
        for (int i = 0; i < 8; i++) //尝试向八个方向走
        {
            int x = sn + point[i][0];
            int y = sm + point[i][1];
            if(check(x,y))  //检查这坐标能不能去
            {
                chess[x][y] = ++step;   //步数加1
                queue[rear][0] = x; //入队列
                queue[rear][1] = y;
                queue[rear][2] = ++step;
                rear++;
            }
        }
    }

    static boolean check(int sn, int sm)    //检查这坐标能不能去
    {
        if(sn<1 || sn>n || sm<1 || sm>m)
        {
            return false;
        }
        if(chess[sn][sm] != -1)
        {
            return false;
        }
        return true;
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值