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

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

问题描述

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

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

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

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

  • 示例 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:

输入: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:

输入: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

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

简单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;
                }
            }
        }
    }
}

原文地址:https://www.cnblogs.com/slowbirdoflsh/p/11666938.html

时间: 2024-10-12 00:19:16

[leetcode 周赛 158] 1222 可以攻击国王的皇后的相关文章

Leetcode-5223 Queens That Can Attack the King(可以攻击国王的皇后)

1 typedef pair<int,int> P; 2 typedef long long ll; 3 #define _for(i,a,b) for(register int i = (a);i < b;i ++) 4 #define _rep(i,a,b) for(register int i = (a);i > b;i --) 5 #define INF 0x3f3f3f3f 6 #define MOD 100000000 7 #define maxn 1003 8 #de

[leetcode 周赛 157] 1217 玩筹码

1217 Play With Chips 玩筹码 题目描述 数轴上放置了一些筹码,每个筹码的位置存在数组 chips 当中. 你可以对 任何筹码 执行下面两种操作之一(不限操作次数,0 次也可以): 将第 i 个筹码向左或者右移动 2 个单位,代价为 0. 将第 i 个筹码向左或者右移动 1 个单位,代价为 1. 最开始的时候,同一位置上也可能放着两个或者更多的筹码. 返回将所有筹码移动到同一位置(任意位置)上所需要的最小代价. 示例 1: 输入:chips = [1,2,3] 输出:1 解释:

[leetcode 周赛 157] 1218 最长定差子序列

1218 Longest Arithmetic Subsequence of Given Difference 最长定差子序列 问题描述 给你一个整数数组 arr 和一个整数 difference,请你找出 arr 中所有相邻元素之间的差等于给定 difference 的等差子序列,并返回其中最长的等差子序列的长度. 示例 1: 输入:arr = [1,2,3,4], difference = 1 输出:4 解释:最长的等差子序列是 [1,2,3,4]. 示例 2: 输入:arr = [1,3,

[leetcode 周赛 157] 1219 黄金矿工

1219 Path with Maximum Gold 黄金矿工 问题描述 你要开发一座金矿,地质勘测学家已经探明了这座金矿中的资源分布,并用大小为 m * n 的网格 grid 进行了标注.每个单元格中的整数就表示这一单元格中的黄金数量:如果该单元格是空的,那么就是 0. 为了使收益最大化,矿工需要按以下规则来开采黄金: 每当矿工进入一个单元,就会收集该单元格中的所有黄金. 矿工每次可以从当前位置向上下左右四个方向走. 每个单元格只能被开采(进入)一次. 不得开采(进入)黄金数目为 0 的单元

[leetcode 周赛 159] 1233 删除子文件夹

1233 Remove Sub-Folders from the Filesystem 删除子文件夹 问题描述 你是一位系统管理员,手里有一份文件夹列表 folder,你的任务是要删除该列表中的所有 子文件夹,并以 任意顺序 返回剩下的文件夹. 我们这样定义「子文件夹」: 如果文件夹?folder[i]?位于另一个文件夹?folder[j]?下,那么?folder[i]?就是?folder[j]?的子文件夹. 文件夹的「路径」是由一个或多个按以下格式串联形成的字符串: /?后跟一个或者多个小写英

【Leetcode周赛】从contest-81开始。(一般是10个contest写一篇文章)

Contest 81 (2018年11月8日,周四,凌晨) 链接:https://leetcode.com/contest/weekly-contest-81 比赛情况记录:结果:3/4, ranking: 440/2797.这次题目似乎比较简单,因为我比赛的时候前三题全做出来了(1:12:39),然后第四题有思路,正在写,没写完,比赛完了写完提交也对了. p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } [821]

【Leetcode周赛】从contest-41开始。(一般是10个contest写一篇文章)

Contest 41 ()(题号) Contest 42 ()(题号) Contest 43 ()(题号) Contest 44 (2018年12月6日,周四上午)(题号653-656) 链接:https://leetcode.com/contest/leetcode-weekly-contest-44 比赛情况记录:就做出来两题,第三题不难,然而就是在算坐标的时候卡住了.orz.结果:2/4,ranking:637/2272.第四题没看题,第三题搞得心情不好了orz. [653]Two Sum

【Leetcode周赛】从contest-71开始。(一般是10个contest写一篇文章)

Contest 71 () Contest 72 () Contest 73 (2019年1月30日模拟) 链接:https://leetcode.com/contest/weekly-contest-73 Contest 74 (2019年1月31日模拟) 链接:https://leetcode.com/contest/weekly-contest-74 Contest 75 (2019年1月31日模拟) 链接:https://leetcode.com/contest/weekly-conte

【Leetcode周赛】从contest-121开始。(一般是10个contest写一篇文章)

Contest 121 (题号981-984)(2019年1月27日) 链接:https://leetcode.com/contest/weekly-contest-121 总结:2019年2月22日补充的报告.当时不想写.rank:1093/3924,AC:2/4.还是太慢了. [984]String Without AAA or BBB(第一题 4分)(Greedy, M) 给了两个数字,A 代表 A 个 'A', B 代表 B 个'B' 在字符串里面.返回一个可行的字符串,字符串中包含 A