• [leetcode 周赛 158] 1222 可以攻击国王的皇后


    1222 Path with Maximum Gold 可以攻击国王的皇后

    问题描述

    在一个 8x8 的棋盘上,放置着若干「黑皇后」和一个「白国王」

    「黑皇后」在棋盘上的位置分布用整数坐标数组 queens 表示,「白国王」的坐标用数组 king 表示。

    「黑皇后」的行棋规定是:横、直、斜都可以走,步数不受限制,但是,不能越子行棋

    请你返回可以直接攻击到「白国王」的所有「黑皇后」的坐标(任意顺序)。

    • 示例 1:
      题图1

    输入:queens = [[0,1],[1,0],[4,0],[0,4],[3,3],[2,4]], king = [0,0]
    输出:[[0,1],[1,0],[3,3]]
    解释
    [0,1] 的皇后可以攻击到国王,因为他们在同一行上。
    [1,0] 的皇后可以攻击到国王,因为他们在同一列上。
    [3,3] 的皇后可以攻击到国王,因为他们在同一条对角线上。
    [0,4] 的皇后无法攻击到国王,因为她被位于 [0,1] 的皇后挡住了。
    [4,0] 的皇后无法攻击到国王,因为她被位于 [1,0] 的皇后挡住了。
    [2,4] 的皇后无法攻击到国王,因为她和国王不在同一行/列/对角线上。

    • 示例 2:
      题图2

    输入:queens = [[0,0],[1,1],[2,2],[3,4],[3,5],[4,4],[4,5]], king = [3,3]
    输出:[[2,2],[3,4],[4,4]]

    • 示例 3:
      题图3

    输入:queens = [[5,6],[7,7],[2,1],[0,7],[1,6],[5,1],[3,7],[0,3],[4,0],[1,2],[6,3],[5,0],[0,4],[2,2],[1,1],[6,4],[5,4],[0,0],[2,6],[4,5],[5,2],[1,4],[7,5],[2,3],[0,5],[4,2],[1,0],[2,7],[0,1],[4,6],[6,1],[0,6],[4,3],[1,7]], king = [3,4]
    输出:[[2,3],[1,4],[1,6],[3,7],[4,3],[5,4],[4,5]]

    • 提示:
      • 1 <= queens.length <= 63
      • queens[0].length == 2
      • 0 <= queens[i][j] < 8
      • king.length == 2
      • 0 <= king[0], king[1] < 8
      • 一个棋盘格上最多只能放置一枚棋子。

    思路

    • 读题
      选取在国王横/竖/斜角八个方向上的最近皇后的位置

    简单BFS

    国王的位置为基准, 每次向周围(八个方向)遍历一遍, 碰到皇后的将其添加到结果, 并删除该方向, 否则则遍历下一周
    直到超出棋盘范围或八个方向上的皇后都遇到了
    BFS

    简单DFS

    国王的位置为基准, 每次选出一个方向深度遍历, 直到遇到皇后或超出边界
    DFS

    代码实现

    纯BFS

    class Solution {
        /**
         * DN 
         * 八个方向 棋盘宽度/高度
         */
        private final static int DN = 8;
        /**
         * 八个方向
         * 上下左右 左上 左下 右上 右下
         */
        private static int[][] direct = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
        /**
         * isFind
         * 确认该方向是否寻找到结果或寻找完
         * 默认初始化为FALSE
         */
        private boolean[] isFind = new boolean[DN];
        /**
         * 国王的位置 (kx, ky)
         */
        private int kx, ky;
    
        public List<List<Integer>> queensAttacktheKing(int[][] queens, int[] king) {
            int[][] area = new int[DN][DN];
    
            // 初始化棋盘 在棋盘上'落子'
            for (int[] queen : queens) {
                int x = queen[0], y = queen[1];
                area[x][y] = 1;
            }
    
            List<List<Integer>> res = new LinkedList<>();
            kx = king[0];
            ky = king[1];
            bfs(area, res, 1);
            return res;
        }
    
        /**
         * 以(kx, ky)为基准点, 八个方向广度遍历第layer环
         * @param area 活动范围 棋盘 8*8
         * @param res 查询结果
         * @param layer 环数
         */
        private void bfs(int[][] area, List<List<Integer>> res, int layer) {
            // 判断是否所有方向都搜索完
            boolean isContinue = hasDirect(isFind);
            if (!isContinue) {
                return;
            }
    
            for (int i = 0; i < direct.length; i++) {
                // 如果该方向没有找完 isFind[i]==false
                if (!isFind[i]) {
                    // 该方向搜索的下一个位置
                    int nx = kx + layer * direct[i][0], ny = ky + layer * direct[i][1];
                    // 如果搜索的位置还在棋盘范围内 则该方向还可以继续搜索
                    if (0 <= nx && nx < 8 && 0 <= ny && ny < 8) {
                        // 该方向遇到'皇后' 该方向'功成身退'
                        if (area[nx][ny] > 0) {
                            isFind[i] = true;
                            // 添加所遇到的'皇后'位置
                            List<Integer> cur = new LinkedList<>();
                            cur.add(nx);
                            cur.add(ny);
                            res.add(cur);
                        }
                    // 该方向搜索位置超出范围 该方向放弃
                    } else {
                        isFind[i] = true;
                    }
                }
            }
    
            // 第layer层搜索完毕 前往下一层
            bfs(area, res, layer + 1);
        }
    
        /**
         * 判断布尔数组中是否还有FALSE值
         * @param booleans 被判断布尔数组
         * @return true 数组中还有FALSE值
         */
        private boolean hasDirect(boolean[] booleans) {
            for (boolean b : booleans) {
                if (!b) {
                    return true;
                }
            }
            return false;
        }
    }
    

    DFS

    class Solution {
        /**
         * DN
         * 八个方向 棋盘宽度/高度
         */
        private final static int DN = 8;
        /**
         * 八个方向
         * 上下左右 左上 左下 右上 右下
         */
        private static int[][] direct = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}, {-1, -1}, {-1, 1}, {1, -1}, {1, 1}};
        /**
         * 国王的位置 (kx, ky)
         */
        private int kx, ky;
    
        public List<List<Integer>> queensAttacktheKing(int[][] queens, int[] king) {
            int[][] area = new int[DN][DN];
    
            // 初始化棋盘 在棋盘上'落子'
            for (int[] queen : queens) {
                int x = queen[0], y = queen[1];
                area[x][y] = 1;
            }
    
            List<List<Integer>> res = new LinkedList<>();
            kx = king[0];
            ky = king[1];
            dfs(area, res);
            return res;
        }
    
        /**
         * 以国王的位置(kx, ky)为基准, 分别深度遍历八个方向
         * @param area 棋盘 活动范围
         * @param res 查询结果
         */
        private void dfs(int[][] area, List<List<Integer>> res) {
            for (int i = 0; i < DN; i++) {
                // 死磕一个方向 直到遇到'皇后'或撞墙
                for (int j = 1; j < DN; j++) {
                    int nx = kx + direct[i][0] * j, ny = ky + direct[i][1] * j;
                    if (0 <= nx && nx < DN && 0 <= ny && ny < DN) {
                        if (area[nx][ny] > 0) {
                            List<Integer> list = new LinkedList<>();
                            list.add(nx);
                            list.add(ny);
                            res.add(list);
                            break;
                        }
                    // '撞墙'就放弃该方向
                    } else {
                        break;
                    }
                }
            }
        }
    }
    
  • 相关阅读:
    C语言printf语法
    Android动画
    【转】Android内存(内存溢出 内存不足 内存低 .)优化详解
    Android dialog在有的手机上宽度不能充满屏幕的问题
    ios单例模式(Singleton)
    给ImageButton设置按下的效果
    Dynamics CRM Entity Relationship Many to Many (N:N)
    Python实现Mysql数据库连接池
    python获取指定时间差的时间
    Visual studio debug—Process with an Id of 5616 is not running的解决方法
  • 原文地址:https://www.cnblogs.com/slowbirdoflsh/p/11666938.html
Copyright © 2020-2023  润新知