有一个 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_xself.start_y = start_yself.end_x = end_xself.end_y = end_yself.dx = dxself.dy = dyself.cur_x = start_xself.cur_y = start_ydef reset(self):self.cur_x = self.start_xself.cur_y = self.start_ydef stopped(self):return self.cur_x == self.end_x and self.cur_y == self.end_ydef advance(self):if not self.stopped():self.cur_x += self.dxself.cur_y += self.dydef 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 Truereturn Falseclass 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 = 0stack = []def check(u):for v in range(u):if stack[u].cross(stack[v]):return Falsereturn Truedef dfs(u):nonlocal resif u == n:res += 1returnif pieces[u] == "rook":directions = rook_directionselif pieces[u] == "queen":directions = queen_directionselif 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] * stepy = positions[u][1] + dire[1] * stepif x < 1 or x > 8 or y < 1 or y > 8:breakstack.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