蓝桥杯 跳马 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,直接返回,跳出循环。不是就把这个坐标存到队列中,以后还得拿来求它的下一八步嘞。存完之后,队列计数器也要加一,并且存完八个,队列第一个数就没用了,要弹出,给下一个数空间。


 

代码如下:

 1 import java.util.Arrays;
 2 import java.util.Deque;
 3 import java.util.LinkedList;
 4 import java.util.Scanner;
 5 
 6 public class Main01 {
 7     //跳马问题
 8     //BFS +算法
 9     //八行两列的马步。
10     static int[][] ma = {{1,2},{-1,2},{1,-2},{-1,-2},{2,1},{-2,1},{2,-1},{-2,-1}};
11     
12     public static void main(String[] args) {
13         Scanner in = new Scanner(System.in);
14         int a = in.nextInt();
15         int b = in.nextInt();
16         int c = in.nextInt();
17         int d = in.nextInt();
18         //ab,初始坐标。cd终点坐标。
19         tiaoma(a, b, c, d);
20     }
21 
22    static void tiaoma(int a, int b,int c, int d){
23         //初始化队列
24        Deque<int[]> B = new LinkedList<>();
25        B.offer(new int[]{a,b});
26         
27       
28        //计数器
29        int cout = 0;
30        int incout =0;
31         
32         //第0步
33        if (a == c && c == d) {
34            System.out.println(cout);
35            return;
36        }
37 
38        //第n步
39        while (true)
40        {
41            for(int[] i : ma) {
42                //临时数组
43                int[] at = new int[2];
44                at[0] = B.getFirst()[0]+i[0];
45                at[1] = B.getFirst()[1]+i[1];
46 
47                //如果是目标值,就直接返回
48                if(Arrays.toString(at).equals(Arrays.toString(new int[]{c, d}) )){
49                    System.out.println(cout+1);
50                      return;
51                }
52 
53                //不是就存入.并且内部计数器+1
54                B.offer(at);
55                incout+=1;
56 
57                //如果存入的数据够了,就让外部计数器+1
58                if (Math.pow(8,cout+1)==incout){
59                    cout+=1;
60                }
61 
62 
63            }  //循环一次之后,新八值就找到了,那么可以弹栈了
64            B.pollFirst();
65        }
66 
67 
68 
69 
70    }
71 }

 

       结果(还是很美的)

如图:

 

 

posted @ 2022-03-17 18:00  星辉与你  阅读(185)  评论(0)    收藏  举报