栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

蓝桥杯 java 跳马问题

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

蓝桥杯 java 跳马问题

问题描述

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

一行四个数字a,b,c,d。


输出格式

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

核心思想:BFS算法(宽搜)

       (不讲解bfs算法,大家可以去b站基本了解,有助于看懂下面的思想和代码)不怕你学不会系列:宽度优先搜索_哔哩哔哩_bilibili宽度优先搜索基本思想https://www.bilibili.com/video/BV1H44y1871A/?spm_id_from=autoNext        使用原因有二:

       一:马有8步选择,不清楚第几步选择,第几次走8步可以到达目标值,所以本质上需要遍历所有结果,也就是要么bfs(深度搜索)要么bfs(宽度搜索)。前者适合解决的是所有路径,后者解决的则是最短路径,所以这里用bfs算法更好

        二:使用的是队列,dfs算法用的是栈,bfs算法用的是队列,两者的区别就是后者是先进先出,那么,我根据当前遍历的值,比如说是(1,1)找到它下八个值之后,我就要把(1,1)弹出去,指针指向下一位(也即是(1,1)下八个值的第一个值,比如是(2,3))。这样保证我们能遍历完所有的值。

程序思想:

1.接受初始步a,b 终点步 c,d


2.判断a ,b 和c,d 是否相等。是就直接输出,螺旋上天。


3.bfs算法求解最短路径


        3.1声明两个计数器,一个表示马真正走了多少步,一个表示队列存了多少种(未计算下一步的)坐标。


        3.2循环,每次都拿队列第一个数来求出八种坐标,并且判断是否我们要的结果,是就步数计数器+1,直接返回,跳出循环。不是就把这个坐标存到队列中,以后还得拿来求它的下一八步嘞。存完之后,队列计数器也要加一,并且存完八个,队列第一个数就没用了,要弹出,给下一个数空间。


代码如下:

import java.util.Arrays;
import java.util.Deque;
import java.util.linkedList;
import java.util.Scanner;

public class Main01 {
    //跳马问题
    //BFS +算法
    //八行两列的马步。
    static int[][] ma = {{1,2},{-1,2},{1,-2},{-1,-2},{2,1},{-2,1},{2,-1},{-2,-1}};
    
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int a = in.nextInt();
        int b = in.nextInt();
        int c = in.nextInt();
        int d = in.nextInt();
        //ab,初始坐标。cd终点坐标。
        tiaoma(a, b, c, d);
    }

   static void tiaoma(int a, int b,int c, int d){
        //初始化队列
       Deque B = new linkedList<>();
       B.offer(new int[]{a,b});
        
      
       //计数器
       int cout = 0;
       int incout =0;
        
        //第0步
       if (a == c && c == d) {
           System.out.println(cout);
           return;
       }

       //第n步
       while (true)
       {
           for(int[] i : ma) {
               //临时数组
               int[] at = new int[2];
               at[0] = B.getFirst()[0]+i[0];
               at[1] = B.getFirst()[1]+i[1];

               //如果是目标值,就直接返回
               if(Arrays.toString(at).equals(Arrays.toString(new int[]{c, d}) )){
                   System.out.println(cout+1);
                     return;
               }

               //不是就存入.并且内部计数器+1
               B.offer(at);
               incout+=1;

               //如果存入的数据够了,就让外部计数器+1
               if (Math.pow(8,cout+1)==incout){
                   cout+=1;
               }


           }  //循环一次之后,新八值就找到了,那么可以弹栈了
           B.pollFirst();
       }




   }
}

       结果(还是很美的)

(这里插几句,为什么不考虑负数的情况,不考虑出界的问题,emmm出界问题确实没考虑。负数的情况就是(1,1)下一步(-1,0)在棋盘上不存在,但是(-1,0)下一步(0,2)回来了,还跑到别的地方去了,那么这到底算可以还是不可以捏?其实你把棋盘化成坐标轴,你会发现它是对称的,也就是如果它真的能走回来,并且走到我们要的答案,那么一定也会有对称的,同样的步数,并且一直在棋盘内的走法,也能走到目标值,所以跑到外界去了,问题不大)

如图:

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/768667.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号