LeetCode 车的可用捕获量

车的可用捕获量


题目来源:https://leetcode-cn.com/problems/available-captures-for-rook

题目


在一个 8 x 8 的棋盘上,有一个白色车(rook)。也可能有空方块,白色的象(bishop)和黑色的卒(pawn)。它们分别以字符 “R”,“.”,“B” 和 “p” 给出。大写字符表示白棋,小写字符表示黑棋。

车按国际象棋中的规则移动:它选择四个基本方向中的一个(北,东,西和南),然后朝那个方向移动,直到它选择停止、到达棋盘的边缘或移动到同一方格来捕获该方格上颜色相反的卒。另外,车不能与其他友方(白色)象进入同一个方格。

返回车能够在一次移动中捕获到的卒的数量。

示例 1:

图片源自 LeetCode 示例 1

输入:
[[".", ".", ".", ".", ".", ".", ".", "."],
 [".", ".", ".", "p", ".", ".", ".", "."],
 [".", ".", ".", "R", ".", ".", ".", "p"],
 [".", ".", ".", ".", ".", ".", ".", "."],
 [".", ".", ".", ".", ".", ".", ".", "."],
 [".", ".", ".", "p", ".", ".", ".", "."],
 [".", ".", ".", ".", ".", ".", ".", "."],
 [".", ".", ".", ".", ".", ".", ".", "."]]
 
输出:3
解释:
在本例中,车能够捕获所有的卒。

示例 2:

图片源自 LeetCode 示例 2

输入:
[[".", ".", ".", ".", ".", ".", ".", "."],
 [".", "p", "p", "p", "p", "p", ".", "."],
 [".", "p", "p", "B", "p", "p", ".", "."],
 [".", "p", "B", "R", "B", "p", ".", "."],
 [".", "p", "p", "B", "p", "p", ".", "."],
 [".", "p", "p", "p", "p", "p", ".", "."],
 [".", ".", ".", ".", ".", ".", ".", "."],
 [".", ".", ".", ".", ".", ".", ".", "."]]

输出:0
解释:
象阻止了车捕获任何卒。

示例 3:

图片源自 LeetCode 示例 3

输入:
[[".", ".", ".", ".", ".", ".", ".", "."],
 [".", ".", ".", "p", ".", ".", ".", "."],
 [".", ".", ".", "p", ".", ".", ".", "."],
 ["p", "p", ".", "R", ".", "p", "B", "."],
 [".", ".", ".", ".", ".", ".", ".", "."],
 [".", ".", ".", "B", ".", ".", ".", "."],
 [".", ".", ".", "p", ".", ".", ".", "."],
 [".", ".", ".", ".", ".", ".", ".", "."]]
 
输出:3
解释: 
车可以捕获位置 b5,d6 和 f5 的卒。

提示:

  • board.length == board[i].length == 8
  • board[i][j] 可以是 ‘R’,’.’,‘B’ 或 ‘p’
  • 只有一个格子上存在 board[i][j] == ‘R’

上面图源均来自 LeetCode

解题思路


稍微吐槽一下,这道题目从文字方面理解题意,总会有很多困扰的地方(下面会提及)。这里结合示例来理解:

  • 白色车(rook,主角)
  • 白色的象(bishop,友方),黑色的卒(pawn,姑且叫敌方),要捕获黑色的卒。

困扰的地方 1:

选择四个基本方向中的一个(北,东,西和南),然后朝那个方向移动,直到它选择停止、到达棋盘的边缘或移动到同一方格来捕获该方格上颜色相反的卒

后面部分的内容,的确有点拗口(移动到同一方格捕获该方格颜色相反的卒),其实这里表示当找到车(R)的时候,就这个车的角度出发,选择北,南,西和东(也就是上下左右),确认可以捕获黑色的卒的数量。

困扰的地方 2:

返回车能够在一次移动中捕获到的卒的数量。

这里单从文字上来看,觉得就是车(R)选择一个方位,一次移动捕获的卒(p)的数量。但结合示例来看,这里的一次,表示的是【北,南,西,东】四个方位算一次。这里有个需要注意的地方,看示例 3,当同个方位有两个黑色的卒时,车(R)只捕获先暴露在面前的卒,后面的卒并不会被捕获。

理解题意后,大致说下解题的思想:

  • 先处理边界问题,防止棋跳出棋盘;
  • 如果遇到白色的象(B,友方),这个时候要停止,因为不能同时在同一个方格中;
  • 如果遇到黑色的卒(p,敌方),说明找到捕获对象,返回值 + 1;
  • 如果遇到的 .(在这里表示空的棋格),表示可以继续移动;

代码实现


class Solution:
    def numRookCaptures(self, board: List[List[str]]) -> int:
        def move(board, x, y, direction):
            # 约束在棋盘内
            while x >= 0 and x < 8 and y >= 0 and y < 8:
                # 遇到象停止
                if board[x][y] == 'B':
                    break

                # 遇到黑色卒捕获
                if board[x][y] == 'p':
                    return True

                # 继续移动
                x += direction[0]
                y += direction[1]
            return False

        directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]

        for x in range(8):
            for y in range(8):
            	# 先定位车(R)的位置
                if board[x][y] == 'R':
                    res = 0
                    # 向四个方位移动,
                    for direction in directions:
                        if move(board, x, y, direction):
                            res += 1
                    return res

实现结果


实现结果


以上就是通过解析题意,根据题意所述的规则直接模拟象棋的移动,从而解决《车的可用捕获量》问题的主要内容。


欢迎关注微信公众号《书所集录》

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值