题目链接 | 3283. 吃掉所有兵需要的最多移动次数 |
---|---|
思路 | 动态规划 |
题解链接 | 相邻相关排列型状压 DP(Python/Java/C++/Go) |
关键点 | 难-状态压缩DP |
时间复杂度 | \(O(n L^2 + n^2 2^n)\) |
空间复杂度 | \(O(n L^2 + n 2^n)\) |
代码实现:
DIRS = ((2, 1), (1, 2), (-1, 2), (-2, 1), (-2, -1), (-1, -2), (1, -2), (2, -1))class Solution:def maxMoves(self, kx: int, ky: int, positions: List[List[int]]) -> int:n = len(positions)# 计算马到兵的步数,等价于计算兵到其余格子的步数distances = [[[-1] * 50 for _ in range(50)] for _ in range(n)]for d, (px, py) in zip(distances, positions):d[px][py] = 0q = [(px, py)]step = 1while q:new_q = []for x, y in q:for dx, dy in DIRS:nx, ny = x + dx, y + dyif 0 <= nx < 50 and 0 <= ny < 50 and d[nx][ny] < 0:d[nx][ny] = stepnew_q.append((nx, ny))q = new_qstep += 1positions.append((kx, ky))u = (1 << n) - 1@cachedef dfs(i: int, mask: int) -> int:if mask == 0:return 0odd = (u ^ mask).bit_count() % 2answer = inf if odd else 0op = min if odd else maxx, y = positions[i]for j, d in enumerate(distances):if mask >> j & 1:answer = op(answer, dfs(j, mask ^ (1 << j)) + d[x][y])return answerreturn dfs(n, u)