首页 > 其他分享 >【LeetCode】每日一题 —— 2056. 棋盘上有效移动组合的数目

【LeetCode】每日一题 —— 2056. 棋盘上有效移动组合的数目

时间:2024-12-04 12:32:57浏览次数:7  
标签:移动 2056 int positions pieces step 棋子 棋盘 LeetCode

一、题目2056. 棋盘上有效移动组合的数目

有一个 8 ∗ 8 8 * 8 8∗8 的棋盘,它包含 n 个棋子(棋子包括车,后和象三种)。给你一个长度为 n 的字符串数组 pieces ,其中 p i e c e s [ i ] pieces[i] pieces[i] 表示第 i 个棋子的类型(车,后或象)。除此以外,还给你一个长度为 n 的二维整数数组positions ,其中 p o s i t i o n s [ i ] = [ r i , c i ] positions[i] = [r_i, c_i] positions[i]=[ri​,ci​] 表示第 i 个棋子现在在棋盘上的位置为 ( r i , c i ) r_i, c_i) ri​,ci​) ,棋盘下标从 1 开始。

棋盘上每个棋子都可以移动 至多一次 。每个棋子的移动中,首先选择移动的 方向 ,然后选择 移动的步数 ,同时你要确保移动过程中棋子不能移到棋盘以外的地方。棋子需按照以下规则移动:

  • 1.车可以 水平或者竖直 从 (r, c) 沿着方向 (r+1, c),(r-1, c),(r, c+1) 或者 (r, c-1) 移动。

  • 2.后可以 水平竖直或者斜对角 从 (r, c) 沿着方向 (r+1, c),(r-1, c),(r, c+1),(r, c-1),(r+1, c+1),(r+1, c-1),(r-1, c+1),(r-1, c-1) 移动。

  • 3.象可以 斜对角 从 (r, c) 沿着方向 (r+1, c+1),(r+1, c-1),(r-1, c+1),(r-1, c-1) 移动。

  • 4.移动组合 包含所有棋子的 移动 。每一秒,每个棋子都沿着它们选择的方向往前移动 一步 ,直到它们到达目标位置。所有棋子从时刻 0 开始移动。如果在某个时刻,两个或者更多棋子占据了同一个格子,那么这个移动组合 不有效 。

请你返回 有效 移动组合的数目。

  • 注意:

    • 初始时,不会有两个棋子 在 同一个位置 。
    • 有可能在一个移动组合中,有棋子不移动。
    • 如果两个棋子 直接相邻 且两个棋子下一秒要互相占据对方的位置,可以将它们在同一秒内 交换位置 。

二、样例

示例1

在这里插入图片描述

  • 输入:pieces = [“rook”], positions = [[1,1]]
  • 输出:15
  • 解释:上图展示了棋子所有可能的移动。

示例 2:

在这里插入图片描述

  • 输入:pieces = [“queen”], positions = [[1,1]]
  • 输出:22
  • 解释:上图展示了棋子所有可能的移动。

示例3:

在这里插入图片描述

  • 输入:pieces = [“bishop”], positions = [[4,3]]
  • 输出:12
  • 解释:上图展示了棋子所有可能的移动。

示例4:

在这里插入图片描述

  • 输入:pieces = [“rook”,“rook”], positions = [[1,1],[8,8]]
  • 输出:223
  • 解释:每个车有 15 种移动,所以总共有 15 * 15 = 225 种移动组合。
    但是,有两个是不有效的移动组合:

1、 将两个车都移动到 (8, 1) ,会导致它们在同一个格子相遇。
2、将两个车都移动到 (1, 8) ,会导致它们在同一个格子相遇。

所以,总共有 225 - 2 = 223 种有效移动组合。
注意,有两种有效的移动组合,分别是一个车在 (1, 8) ,另一个车在 (8, 1) 。
即使棋盘状态是相同的,这两个移动组合被视为不同的,因为每个棋子移动操作是不相同的。

三、数据范围

  • n == pieces.length
  • n == positions.length
  • 1 <= n <= 4
  • pieces 只包含字符串 “rook” ,“queen” 和 “bishop” 。
  • 棋盘上最多只有一个后。
  • 1 <= r i r_i ri​, c i c_i ci​ <= 8
  • 每一个 p o s i t i o n s [ i ] positions[i] positions[i] 互不相同。

四、思路

首先数据范围很小,可以无脑进行dfs/bfs搜索出所有的可能,这里使用bfs常数大一点,但是比较好写一点。

每次取出一个棋子,放入所有移动的可能(包括不移动),放完所有的棋子检查当前棋盘和合法性即可。

五、代码

class Solution {

public:
    int n;
    int dir[8][2] = {{-1, 0}, {-1, 1}, {0, 1},  {1, 1},
                     {1, 0},  {1, -1}, {0, -1}, {-1, -1}};
    int vis[10][10];
    int countCombinations(vector<string>& pieces,
                          vector<vector<int>>& positions) {
        n = pieces.size();
        vector<pair<int, int>> moves;
        return bfs(pieces, positions, moves);
    }

    int bfs(vector<string>& pieces, vector<vector<int>>& positions,
            vector<pair<int, int>>& moves) {
        // 队列用于BFS,保存每一层的状态
        queue<pair<vector<pair<int, int>>, int>> q; // 状态,当前棋子索引
        q.push({moves, 0});

        int totalCombinations = 0;

        while (!q.empty()) {
            auto [currentMoves, p] = q.front();
            q.pop();

            if (p == n) {
                if (valid(positions, currentMoves)) {
                    totalCombinations++;
                }
                continue;
            }

            int start = (pieces[p] == "bishop" ? 1 : 0);
            int add = (pieces[p] == "queen" ? 1 : 2);
            int x = positions[p][0], y = positions[p][1];

            // 保持当前棋子不动
            currentMoves.push_back({0, 0});
            q.push({currentMoves, p + 1});
            currentMoves.pop_back();

            // 遍历所有可能的移动方向
            for (int d = start; d < 8; d += add) {
                int step = 1;
                int nx = x + dir[d][0], ny = y + dir[d][1];
                while (nx >= 1 && nx <= 8 && ny >= 1 && ny <= 8) {
                    currentMoves.push_back({d, step});
                    q.push({currentMoves, p + 1});
                    currentMoves.pop_back();
                    nx += dir[d][0];
                    ny += dir[d][1];
                    step++;
                }
            }
        }
        return totalCombinations;
    }

    bool valid(vector<vector<int>>& positions, vector<pair<int, int>>& moves) {
        memset(vis, 0, sizeof(vis));
        int done = 0;
        for (auto& [d, step] : moves) {
            done += (step == 0);
        }
        for (int r = 1; done < n; r++) {
            for (int i = 0; i < n; i++) {
                auto& [d, step] = moves[i];
                int x = positions[i][0] + min(step, r) * dir[d][0];
                int y = positions[i][1] + min(step, r) * dir[d][1];
                if (vis[x][y] == r)
                    return false;
                vis[x][y] = r;
                if (step == r)
                    done++;
            }
        }
        return true;
    }
};

标签:移动,2056,int,positions,pieces,step,棋子,棋盘,LeetCode
From: https://blog.csdn.net/Antonio915/article/details/144235982

相关文章

  • 【Leetcode Top 100】138. 随机链表的复制
    问题背景给你一个长度为nnn的链表,每个节点包含一个额外增加的随机指针ra......
  • 【Leetcode 每日一题】2056. 棋盘上有效移动组合的数目
    问题背景有一个8×88\times88×8的棋盘,它包含n......
  • 【力扣】3274. 检查棋盘方格颜色是否相同
    一、题目给你两个字符串coordinate1和coordinate2,代表8x8国际象棋棋盘上的两个方格的坐标。以下是棋盘格的参考图:如果这两个方格颜色相同,返回true,否则返回false。坐标总是表示有效的棋盘方格。坐标的格式总是先字母(表示列),再数字(表示行)。示例:输入:coordinate1......
  • 代码随想录算法训练营第三十六天|LeetCode1049.最后一块石头的重量II、LeetCode494.目
    前言打卡代码随想录算法训练营第49期第三十六天...φ(0 ̄*)啦啦啦_φ(* ̄0 ̄)′首先十分推荐学算法的同学可以先了解一下代码随想录,可以在B站卡哥B站账号、代码随想录官方网站代码随想录了解,卡哥清晰易懂的算法教学让我直接果断关注,也十分有缘和第49期的训练营大家庭一起进步。Le......
  • leetcode 面试17.26 稀疏相似度
    一个文档可以用某个int集合来表示,两个文档的相似度定义为对应集合的交集大小除以并集大小,例如{1,5,3}与{1,7,2,3}的相似度为0.4。给定n个相似度很稀疏的文档,返回所有相似度大于0的组合。1<=n<=500,1<=set[i]<=500分析:采用类似倒排索引的做法,对集合中的每个int,记录在哪些文档中......
  • LeetCode刷题 -- 分治快排
    目录颜色分类题目解析算法原理代码排序数组题目解析算法原理代码数组中第K个最大元素题目解析算法原理代码LCR159.库存管理III题目解析算法原理代码颜色分类题目链接题目解析数组分为三块算法原理1.如果nums[i]==0,++left,i++下标对应元素交换,先+......
  • 2024/12/3 【哈希表】 LeetCode 242.有效的字母异位词 【x】
    题目链接:https://leetcode.cn/problems/valid-anagram/description/解法1:classSolution:defisAnagram(self,s:str,t:str)->bool:record=[0]*26foriins:record[ord(i)-ord('a')]+=1fori......
  • 3274. 检查棋盘方格颜色是否相同
    给你两个字符串coordinate1和coordinate2,代表8x8国际象棋棋盘上的两个方格的坐标。以下是棋盘的参考图。如果这两个方格颜色相同,返回true,否则返回false。坐标总是表示有效的棋盘方格。坐标的格式总是先字母(表示列),再数字(表示行)。示例1:输入:coordinate1="a1",coo......
  • 搞定leetcode面试经典150题之哈希算法
    系列博客目录搞定leetcode面试经典150题之哈希算法搞定leetcode面试经典150题之双指针搞定leetcode面试经典150题之滑动窗口文章目录系列博客目录理论知识1.哈希函数(HashFunction)2.哈希表(HashTable)通过HashMap实现3.哈希算法的应用4.哈希算法的时间复杂度编......
  • 2024/12/2【链表】LeetCode 142 环形链表 II 【X】
    题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/description/题解链接:https://www.programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC没做出来......