<蓝桥杯> 试题 算法训练 跳马Java代码+思路

试题 算法训练 跳马

问题描述`

资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
  一个8×8的棋盘上有一个马初始位置为(a,b),他想跳到(c,d),问是否可以?如果可以,最少要跳几步?
输入格式
  一行四个数字a,b,c,d。
输出格式
  如果跳不到,输出-1;否则输出最少跳到的步数。
样例输入
1 1 2 3
样例输出
1
数据规模和约定
  0<a,b,c,d≤8且都是整数。

注意到,规模非常小,所以可以使用暴力解法解决!

思路

这题用广度搜索优先算法(BFS)
具体思路就是,我拿到当前位置(a,b),存入链表中,判别下是否等于目标位置(c,d)。如果是直接返回次数,如果不是,我们将(a,b)可以走的所有下一个位置都加入到链表中,直到找到一个位置等于(c,d)。

下面贴出Java代码

import java.util.*;

import static java.lang.System.in;
import static java.lang.System.out;

public class Main {
    static Deque<int[]> list = new LinkedList<int[]>(); // 这个集合记录每一次走的过程,因为只涉及插入和删除,我用Deque。
    static int[][] steps = new int[][]{{1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1,}, {-2, 1},
            {-2, -1}};  // 因为马只能走“日”,所以这个二维数组给出所有马能够走的方向,共八方。

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt(), b = sc.nextInt(), c = sc.nextInt(), d = sc.nextInt(), len = steps.length;
        out.println(getCount(a, b, c, d, len));
    }

    /**
     * @param a 对应题目中的a
     * @param b 对应题目中的b
     * @param c 对应题目中的c
     * @param d 对应题目中的d
     * @param len steps数组的长度
     * @return 返回最短的次数
     */
    public static int getCount(int a, int b, int c, int d, int len) {
        list.offer(new int[]{a, b}); // 先将起始位置加进来
        int count = 0, innerCount = 0; //count为最后的返回值,innerCount后面会讲
        if (list.getFirst()[0] == c && list.getFirst()[1] == d) { // 如果起始位置等于最终的位置,我们直接返回count。
            return count;
        }

        boolean flag = true;  // 死循环退出标识
        while (flag) {
            for (int i = 0; i < len; i++) {  // 最外层的for循环是控制马走的方向
                int[] at = new int[2]; // 临时的at数组装载每一次当前位置的下一个位置
                for (int j = 0; j < 2; j++) { // 该循环每次都更新马当前位置可走的方向,比方说马当前在(1,1),完成一次该for循环,马就出现了下一个可以走的位置,存到list里面,
                                                // 如果两层for循环都完成马就会出现8个当前位置可以走的下一个位置,存入list中
                    at[j] = list.getFirst()[j] + steps[i][j];
                }
                list.offer(at); // 存入下一个位置到list
                innerCount++; // 每一个存入innerCount就会+1,当这里的加1并不能表示次数。因为如果马用的步数为1的时候,innerCount的会是8,而步数用的是2时,innerCount为64
                if (at[0] == c && at[1] == d) { // 符号条件,则把退出表示设置为false
                    flag = false;
                    break;
                }
            }
            if (Math.pow(8, count + 1) == innerCount) // 基于42行的说法,所以有了当前的判别式。
                count++;
            list.pollFirst(); // 当当前位置下一步可走的8个方向存入list中,我们删除当前方向,判别下一个方向
        }
        return count + 1;
    }

}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值