3283. 吃掉所有兵需要的最多移动次数
给你一个 50 x 50
的国际象棋棋盘,棋盘上有 一个 马和一些兵。给你两个整数 kx
和 ky
,其中 (kx, ky)
表示马所在的位置,同时还有一个二维数组 positions
,其中 positions[i] = [xi, yi]
表示第 i
个兵在棋盘上的位置。
Alice 和 Bob 玩一个回合制游戏,Alice 先手。玩家的一次操作中,可以执行以下操作:
Alice 的目标是 最大化 两名玩家的 总 移动次数,直到棋盘上不再存在兵,而 Bob 的目标是 最小化 总移动次数。
假设两名玩家都采用 最优 策略,请你返回 Alice 可以达到的 最大 总移动次数。
在一次 移动 中,如下图所示,马有 8 个可以移动到的位置,每个移动位置都是沿着坐标轴的一个方向前进 2 格,然后沿着垂直的方向前进 1 格。
示例 1:
输入:kx = 1, ky = 1, positions = [[0,0]]
输出:4
解释:
马需要移动 4 步吃掉 (0, 0)
处的兵。
示例 2:
输入:kx = 0, ky = 2, positions = [[1,1],[2,2],[3,3]]
输出:8
解释:
(2, 2)
处的兵,移动马吃掉它需要 2 步:(0, 2) -> (1, 4) -> (2, 2)
。(3, 3)
处的兵,移动马吃掉它需要 2 步:(2, 2) -> (4, 1) -> (3, 3)
。(1, 1)
处的兵,移动马吃掉它需要 4 步:(3, 3) -> (4, 1) -> (2, 2) -> (0, 3) -> (1, 1)
。示例 3:
输入:kx = 0, ky = 0, positions = [[1,2],[2,4]]
输出:3
解释:
(2, 4)
处的兵,移动马吃掉它需要 2 步:(0, 0) -> (1, 2) -> (2, 4)
。注意,(1, 2)
处的兵不会被吃掉。(1, 2)
处的兵,移动马吃掉它需要 1 步:(2, 4) -> (1, 2)
。
提示:
0 <= kx, ky <= 49
1 <= positions.length <= 15
positions[i].length == 2
0 <= positions[i][0], positions[i][1] <= 49
positions[i]
两两互不相同。0 <= i < positions.length
,都有 positions[i] != [kx, ky]
。原站题解
golang 解法, 执行用时: 261 ms, 内存消耗: 15 MB, 提交时间: 2024-10-22 09:29:06
func maxMoves(kx, ky int, positions [][]int) int { type pair struct{ x, y int } dirs := []pair{{2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}, {1, -2}, {2, -1}} n := len(positions) // 计算马到兵的步数,等价于计算兵到其余格子的步数 dis := make([][50][50]int, n) for i, pos := range positions { d := &dis[i] for j := range d { for k := range d[j] { d[j][k] = -1 } } px, py := pos[0], pos[1] d[px][py] = 0 q := []pair{{px, py}} for step := 1; len(q) > 0; step++ { tmp := q q = nil for _, p := range tmp { for _, dir := range dirs { x, y := p.x+dir.x, p.y+dir.y if 0 <= x && x < 50 && 0 <= y && y < 50 && d[x][y] < 0 { d[x][y] = step q = append(q, pair{x, y}) } } } } } positions = append(positions, []int{kx, ky}) u := 1<<n - 1 f := make([][]int, 1<<n) for i := range f { f[i] = make([]int, n+1) } for mask := 1; mask < 1<<n; mask++ { for i, p := range positions { x, y := p[0], p[1] odd := bits.OnesCount(uint(u^mask))%2 > 0 if odd { f[mask][i] = math.MaxInt } op := func(a, b int) int { if odd { return min(a, b) } return max(a, b) } for s := uint(mask); s > 0; s &= s - 1 { j := bits.TrailingZeros(s) f[mask][i] = op(f[mask][i], f[mask^1<<j][j]+dis[j][x][y]) } } } return f[u][n] }
python3 解法, 执行用时: 9549 ms, 内存消耗: 23 MB, 提交时间: 2024-10-22 09:28:48
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) # 计算马到兵的步数,等价于计算兵到其余格子的步数 dis = [[[-1] * 50 for _ in range(50)] for _ in range(n)] for d, (px, py) in zip(dis, positions): d[px][py] = 0 q = [(px, py)] step = 1 while q: tmp = q q = [] for p in tmp: for dx, dy in DIRS: x, y = p[0] + dx, p[1] + dy if 0 <= x < 50 and 0 <= y < 50 and d[x][y] < 0: d[x][y] = step q.append((x, y)) step += 1 positions.append((kx, ky)) u = (1 << n) - 1 f = [[0] * (n + 1) for _ in range(1 << n)] for mask in range(1, 1 << n): for i, (x, y) in enumerate(positions): odd = (u ^ mask).bit_count() % 2 res = inf if odd else 0 op = min if odd else max for j, d in enumerate(dis): if mask >> j & 1: res = op(res, f[mask ^ (1 << j)][j] + d[x][y]) f[mask][i] = res return f[-1][n]
java 解法, 执行用时: 445 ms, 内存消耗: 47.7 MB, 提交时间: 2024-10-22 09:28:33
class Solution { private static final int[][] DIRS = {{2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}, {1, -2}, {2, -1}}; public int maxMoves(int kx, int ky, int[][] positions) { int n = positions.length; // 计算马到兵的步数,等价于计算兵到其余格子的步数 int[][][] dis = new int[n][50][50]; for (int i = 0; i < n; i++) { int[][] d = dis[i]; for (int j = 0; j < 50; j++) { Arrays.fill(d[j], -1); } int px = positions[i][0]; int py = positions[i][1]; d[px][py] = 0; List<int[]> q = List.of(new int[]{px, py}); for (int step = 1; !q.isEmpty(); step++) { List<int[]> tmp = q; q = new ArrayList<>(); for (int[] p : tmp) { for (int[] dir : DIRS) { int x = p[0] + dir[0]; int y = p[1] + dir[1]; if (0 <= x && x < 50 && 0 <= y && y < 50 && d[x][y] < 0) { d[x][y] = step; q.add(new int[]{x, y}); } } } } } int u = (1 << n) - 1; int[][] f = new int[1 << n][n + 1]; for (int mask = 1; mask < (1 << n); mask++) { for (int i = 0; i <= n; i++) { int x = i < n ? positions[i][0] : kx; int y = i < n ? positions[i][1] : ky; if (Integer.bitCount(u ^ mask) % 2 == 0) { // Alice 操作 for (int j = 0; j < n; j++) { if ((mask >> j & 1) > 0) { f[mask][i] = Math.max(f[mask][i], f[mask ^ (1 << j)][j] + dis[j][x][y]); } } } else { // Bob 操作 f[mask][i] = Integer.MAX_VALUE; for (int j = 0; j < n; j++) { if ((mask >> j & 1) > 0) { f[mask][i] = Math.min(f[mask][i], f[mask ^ (1 << j)][j] + dis[j][x][y]); } } } } } return f[u][n]; } }
cpp 解法, 执行用时: 802 ms, 内存消耗: 320.6 MB, 提交时间: 2024-10-22 09:28:20
class Solution { static constexpr int dirs[8][2] = {{2, 1}, {1, 2}, {-1, 2}, {-2, 1}, {-2, -1}, {-1, -2}, {1, -2}, {2, -1}}; public: int maxMoves(int kx, int ky, vector<vector<int>>& positions) { int n = positions.size(); int dis[n][50][50]; memset(dis, -1, sizeof(dis)); // 计算马到兵的步数,等价于计算兵到其余格子的步数 for (int i = 0; i < n; i++) { int px = positions[i][0], py = positions[i][1]; dis[i][px][py] = 0; vector<pair<int, int>> q = {{px, py}}; for (int step = 1; !q.empty(); step++) { vector<pair<int, int>> tmp; for (auto& [qx, qy] : q) { for (auto& [dx, dy] : dirs) { int x = qx + dx, y = qy + dy; if (0 <= x && x < 50 && 0 <= y && y < 50 && dis[i][x][y] < 0) { dis[i][x][y] = step; tmp.emplace_back(x, y); } } } q = move(tmp); } } positions.push_back({kx, ky}); int u = (1 << n) - 1; vector<vector<int>> f(1 << n, vector<int>(n + 1)); for (int mask = 1; mask < (1 << n); mask++) { for (int i = 0; i <= n; i++) { int x = positions[i][0], y = positions[i][1]; if (__builtin_parity(u ^ mask) == 0) { // Alice 操作 for (int j = 0; j < n; j++) { if (mask >> j & 1) { f[mask][i] = max(f[mask][i], f[mask ^ (1 << j)][j] + dis[j][x][y]); } } } else { // Bob 操作 f[mask][i] = INT_MAX; for (int j = 0; j < n; j++) { if (mask >> j & 1) { f[mask][i] = min(f[mask][i], f[mask ^ (1 << j)][j] + dis[j][x][y]); } } } } } return f[u][n]; } };