蓝桥杯 算法训练 跳马 (Java)

文章介绍了如何使用BFS(广度优先搜索)算法解决8x8棋盘上马从(a,b)移动到(c,d)的最短步数问题。通过定义马的跳跃规则,存储可能的位置,并利用队列进行广度优先遍历,当找到目标位置时输出步数。提供的Java代码示例展示了算法的详细过程。
摘要由CSDN通过智能技术生成

问题描述:

一个8×8的棋盘上有一个马初始位置为(a,b),他想跳到(c,d),问是否可以?如果可以,最少要跳几步?

输入格式:

 如果跳不到,输出-1;否则输出最少跳到的步数。

输出格式:

1 1 2 3

样例输出:

1

数据规模和约定:

0<a,b,c,d≤8且都是整数。

思路:

  1. 跳马问题,我们首先想到的就是运用蓝桥杯中的暴力算法的模式,这里我使用bdf(宽度优先算法)

不了解的小伙伴可以看看这个视频了解了解:图Graph, 深度优先遍历(DFS), 广度优先遍历(BFS)【数据结构和算法入门9】_哔哩哔哩_bilibili (视频的17:05中有讲到)

  1. 首先让我们来了解跳马的一个原则,来上图咯!~~~~

相信大家都有了解过中国的象棋,根据马行日,我们可以建立如此的数学模型,假设此时马的坐标位置为x,y那么它可以走的位置有上图八种情况。

  1. 此时我们就可以把x和y八种不同的情况分别储存在一维数组中去。

int dx[] = new int[]{2, 1, 2, 1, -2, -1, -2, -1};
int dy[] = new int[]{1, 2, -1, -2, 1, 2, -1, -2};

  1. 说到暴力算法,这时为啥呢,还是回到上面的那张图,在第一层中,马可以走以上八个点,而八个点中的每一个点又可以有八个点,而当我们每遍历完一层,还没有找到目标点的情况下,那么这个时候就已经算上马走了一次了,(比如说马要达到n层才能达到那个点,现在第一层的所有可能都已经发生了,但是还没有到达,所以马就已经算上走了一步了,直到它走到n层中的某一个点时,循环就结束了,对于前面所走的点大家的机会都是公平的,因此最短路径的问题就完美解决了),那如果下一次跳就到达了目标的位置,我们可以知道才这一层中前面遍历过的点已经是和这个目标点是一致的基本次数都是一样,而下一步就到达目标位置则说明前面的所有出现的情况都是相同的,即使后面的尝试再次到达目标位置的话,都会使得跳到的次数比这次的还要来得多。

  1. 现在我们首先来看看部分代码:

 Deque<int []> temp = new LinkedList<>();
        temp.offer(new int[]{a,b});

        if (a == c && b == d){
            System.out.println(0);
        }


        while (true){

            for (int i = 0; i < 8; i++){
                int[] tempArr = new int[2];
                tempArr[0] = temp.getFirst()[0] + dx[i];
                tempArr[1] = temp.getFirst()[1] + dy[i];


                if (tempArr[0] == c && tempArr[1] == d){
                    System.out.println(count1 + 1);
                    return;
                }

                temp.offer(tempArr);

                count2++;

                if (Math.pow(8,count1+1) == count2){
                    count1++;
                }


            }
            temp.pollFirst();

        }

bdf算法,我们这里使用Deque类,它主要是一个队列的类。这里我们主要知道它几个简单的方法即可。

offer():把元素入队 getFirst():取得队头的第一个元素 pollFirst();把队头的第一个元素弹出去

这里仅仅是本人的主观上的理解,想要更详细的了解还请看看以下链接:http://t.csdn.cn/TZgn6

而这里的代码和上面的思路相通,不懂的可以结合代码多理解理解上面的思路。补充一点:每当我们遍历完一层的时候就把刚开始的那个点(也就是队头元素弹出去)

完整代码展示:


import java.util.*;

/**
 * @author Qik~
 * @create 2023-01-16 19:37
 */
public class Main {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);

        int a = scan.nextInt();
        int b = scan.nextInt();
        int c = scan.nextInt();
        int d = scan.nextInt();
        
        //用来计算结果和判断该点是否测试完成八种情况的跳跃
        int count1 = 0;
        int count2 = 0;
        
        //马儿可能跳跃的点的位置
        int dx[] = new int[]{2, 1, 2, 1, -2, -1, -2, -1};
        int dy[] = new int[]{1, 2, -1, -2, 1, 2, -1, -2};

        Deque<int []> temp = new LinkedList<>();
        
        temp.offer(new int[]{a,b});

        if (a == c && b == d){
            System.out.println(0);
            return;
        }


        while (true){

            for (int i = 0; i < 8; i++){
                int[] tempArr = new int[2];
                tempArr[0] = temp.getFirst()[0] + dx[i];
                tempArr[1] = temp.getFirst()[1] + dy[i];


                if (tempArr[0] == c && tempArr[1] == d){
                    System.out.println(count1 + 1);
                    return;
                }

                temp.offer(tempArr);

                count2++;

                if (Math.pow(8,count1+1) == count2){
                    count1++;
                }


                
            }
            temp.pollFirst();

        }
    }

   

}

测试结果:

运 用 贪 心 算 法 ,vc++ 语 言 编 写 , 可 单 步 输 出 结 果 【问题描述】 跳马问题也称骑士遍历、马踏棋盘问题:在8*8方格的棋盘上,从任意指定的方格出发,为象棋中的马寻找一条走遍棋盘每一格并且只经过一次的一条路径。 考虑国际象棋棋盘上某个位置的一只马,它是否可能只走63步,正好走过除起点外的其他63个位置各一次?如果有一种这样的走法,则称所走的这条路线为一条马的周游路线。试设计一个算法找出这样一条马的周游路线。 在一个8×8的方格棋盘中,按照国际象棋中马的行走规则从棋盘上的某一方格出发,开始在棋盘上周游,如果能不重复地走遍棋盘上的每一个方格, 这样的一条周游路线在数学上被称为国际象棋盘上马的哈密尔顿链。请你设计一个程序,从键盘输入一个起始方格的坐标,由计算机自动寻找并打印 【算法描述】 本题有较多方法求解,在此仅对回溯法进行分析。 一只马在棋盘的某一点,它可以朝8个方向前进,方向向量分别是:(2,1)、(2,-1)、(1,2)、(1,-2)、(-2,1)、(-2,-1)、(-1,2)、(-1,-2)。从中任选择一个方向前进,到达新的位置。在从新的位置选择一个方向前进,继续,直到无法前进为止。无法前进可能有如下原因:下一位置超出边界、下一位置已经被访问过。当马已经无法前进时,就回退到上一位置,从新选择一个新的方向前进;如果还是无法前进,就再回退到上一位置……
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Luca-s-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值