20241204: 2056. 棋盘上有效移动组合的数目
有一个 8 x 8
的棋盘,它包含 n
个棋子(棋子包括车,后和象三种)。给你一个长度为 n
的字符串数组 pieces
,其中 pieces[i]
表示第 i
个棋子的类型(车,后或象)。除此以外,还给你一个长度为 n
的二维整数数组 positions
,其中 positions[i] = [ri, ci]
表示第 i
个棋子现在在棋盘上的位置为 (ri, ci)
,棋盘下标从 1 开始。
棋盘上每个棋子都可以移动 至多一次 。每个棋子的移动中,首先选择移动的 方向 ,然后选择 移动的步数 ,同时你要确保移动过程中棋子不能移到棋盘以外的地方。棋子需按照以下规则移动:
- 车可以 水平或者竖直 从
(r, c)
沿着方向(r+1, c)
,(r-1, c)
,(r, c+1)
或者(r, c-1)
移动。 - 后可以 水平竖直或者斜对角 从
(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)
移动。 - 象可以 斜对角 从
(r, c)
沿着方向(r+1, c+1)
,(r+1, c-1)
,(r-1, c+1)
,(r-1, c-1)
移动。
移动组合 包含所有棋子的 移动 。每一秒,每个棋子都沿着它们选择的方向往前移动 一步 ,直到它们到达目标位置。所有棋子从时刻 0
开始移动。如果在某个时刻,两个或者更多棋子占据了同一个格子,那么这个移动组合 不有效 。
请你返回 有效 移动组合的数目。
注意:
- 初始时,不会有两个棋子 在 同一个位置 。
- 有可能在一个移动组合中,有棋子不移动。
- 如果两个棋子 直接相邻 且两个棋子下一秒要互相占据对方的位置,可以将它们在同一秒内 交换位置 。
class Movement: def __init__(self, start_x, start_y, end_x, end_y, dx, dy): self.start_x = start_x self.start_y = start_y self.end_x = end_x self.end_y = end_y self.dx = dx self.dy = dy self.cur_x = start_x self.cur_y = start_y def reset(self): self.cur_x = self.start_x self.cur_y = self.start_y def stopped(self): return self.cur_x == self.end_x and self.cur_y == self.end_y def advance(self): if not self.stopped(): self.cur_x += self.dx self.cur_y += self.dy def cross(self, other): # 每次判断是否相遇时需要重置 cur self.reset() other.reset() while not self.stopped() or not other.stopped(): self.advance() other.advance() if self.cur_x == other.cur_x and self.cur_y == other.cur_y: return True return False class Solution: def countCombinations(self, pieces: List[str], positions: List[List[int]]) -> int: rook_directions = [[1, 0], [-1, 0], [0, 1], [0, -1]] # 上下左右,车的移动方向 bishop_directions = [[1, 1], [1, -1], [-1, 1], [-1, -1]] # 斜,象的移动 queen_directions = rook_directions + bishop_directions # 后的移动 n = len(pieces) res = 0 stack = [] def check(u): for v in range(u): if stack[u].cross(stack[v]): return False return True def dfs(u): nonlocal res if u == n: res += 1 return if pieces[u] == "rook": directions = rook_directions elif pieces[u] == "queen": directions = queen_directions elif pieces[u] == "bishop": directions = bishop_directions # 处理第 u 个棋子原地不动的情况 stack.append(Movement(positions[u][0], positions[u][1], positions[u][0], positions[u][1], 0, 0)) if check(u): dfs(u + 1) stack.pop() # 枚举第 u 个棋子在所有方向、所有步数的情况 for dire in directions: for step in range(1, 8): x = positions[u][0] + dire[0] * step y = positions[u][1] + dire[1] * step if x < 1 or x > 8 or y < 1 or y > 8: break stack.append(Movement(positions[u][0], positions[u][1], x, y, dire[0], dire[1])) if check(u): dfs(u + 1) stack.pop() dfs(0) return res
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程