From da733a56affbf9adfe37916c76f390038139e978 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sat, 22 Mar 2025 09:55:49 +0200 Subject: [PATCH 1/4] Improved task 3283 --- .../Solution.kt | 155 ++++++++++-------- 1 file changed, 84 insertions(+), 71 deletions(-) diff --git a/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt b/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt index 3acfc534d..cddfa61e3 100644 --- a/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt +++ b/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt @@ -1,101 +1,114 @@ package g3201_3300.s3283_maximum_number_of_moves_to_kill_all_pawns // #Hard #Array #Math #Breadth_First_Search #Bit_Manipulation #Bitmask #Game_Theory -// #2024_09_11_Time_638_ms_(100.00%)_Space_62.2_MB_(87.50%) +// #2025_03_22_Time_119_ms_(100.00%)_Space_66.82_MB_(100.00%) -import java.util.LinkedList -import java.util.Queue import kotlin.math.max import kotlin.math.min class Solution { - private lateinit var distances: Array - private lateinit var memo: Array?> - - fun maxMoves(kx: Int, ky: Int, positions: Array): Int { + private fun initializePositions(positions: Array, pos: Array, kx: Int, ky: Int) { val n = positions.size - distances = Array(n + 1) { IntArray(n + 1) { 0 } } - memo = Array?>(n + 1) { arrayOfNulls(1 shl n) } - // Calculate distances between all pairs of positions (including knight's initial position) - for (i in 0 until n) { - distances[n][i] = calculateMoves(kx, ky, positions[i][0], positions[i][1]) - for (j in i + 1 until n) { - val dist = - calculateMoves( - positions[i][0], - positions[i][1], - positions[j][0], - positions[j][1], - ) - distances[j][i] = dist - distances[i][j] = distances[j][i] - } + for (i in 0.., pos: Array, distances: Array) { + val n = positions.size + for (i in 0..(50) { BooleanArray(50) } + visited[positions[i][0]][positions[i][1]] = true + val que: java.util.Queue = java.util.ArrayDeque() + que.offer(intArrayOf(positions[i][0], positions[i][1])) + var steps = 1 + while (!que.isEmpty() && count > 0) { + var size = que.size + while (size-- > 0) { + val cur = que.poll() + val x = cur[0] + val y = cur[1] + for (d in DIRECTIONS) { + val nx = x + d[0] + val ny = y + d[1] + if (0 <= nx && nx < 50 && 0 <= ny && ny < 50 && !visited[nx][ny]) { + que.offer(intArrayOf(nx, ny)) + visited[nx][ny] = true + val j = pos[nx][ny] + if (j > i) { + distances[j][i] = steps + distances[i][j] = distances[j][i] + if (--count == 0) { + break + } + } + } + } + if (count == 0) { + break + } } + steps++ } } - memo[lastPos]!![remainingPawns] = result - return result } - private fun calculateMoves(x1: Int, y1: Int, x2: Int, y2: Int): Int { - if (x1 == x2 && y1 == y2) { - return 0 - } - val visited = Array(50) { BooleanArray(50) } - val queue: Queue = LinkedList() - queue.offer(intArrayOf(x1, y1, 0)) - visited[x1][y1] = true - while (queue.isNotEmpty()) { - val current = queue.poll() - val x = current[0] - val y = current[1] - val moves = current[2] - for (move in KNIGHT_MOVES) { - val nx = x + move[0] - val ny = y + move[1] - if (nx == x2 && ny == y2) { - return moves + 1 - } - if (nx >= 0 && nx < 50 && ny >= 0 && ny < 50 && !visited[nx][ny]) { - queue.offer(intArrayOf(nx, ny, moves + 1)) - visited[nx][ny] = true + private fun calculateDP(n: Int, distances: Array): Int { + val m = (1 shl n) - 1 + val dp = Array(1 shl n) { IntArray(n + 1) } + for (mask in 1..<(1 shl n)) { + val isEven = (Integer.bitCount(m xor mask)) % 2 == 0 + for (i in 0..n) { + var result = 0 + if (isEven) { + for (j in 0.. 0) { + result = max( + result, + (dp[mask xor (1 shl j)][j] + distances[i][j]), + ) + } + } + } else { + result = Int.Companion.MAX_VALUE + for (j in 0.. 0) { + result = min( + result, + (dp[mask xor (1 shl j)][j] + distances[i][j]), + ) + } + } } + dp[mask][i] = result } } - // Should never reach here if input is valid - return -1 + return dp[m][n] + } + + fun maxMoves(kx: Int, ky: Int, positions: Array): Int { + val n = positions.size + val pos = Array(50) { IntArray(50) } + initializePositions(positions, pos, kx, ky) + val distances = Array(n + 1) { IntArray(n + 1) } + calculateDistances(positions, pos, distances) + return calculateDP(n, distances) } companion object { - private val KNIGHT_MOVES = arrayOf( - intArrayOf(-2, -1), + private val DIRECTIONS = arrayOf( + intArrayOf(2, 1), + intArrayOf(1, 2), + intArrayOf(-1, 2), intArrayOf(-2, 1), + intArrayOf(-2, -1), intArrayOf(-1, -2), - intArrayOf(-1, 2), intArrayOf(1, -2), - intArrayOf(1, 2), intArrayOf(2, -1), - intArrayOf(2, 1), ) } } From 9dcb8acc4bfd4eded20b70e201e4ab8d5c877596 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sat, 22 Mar 2025 09:57:50 +0200 Subject: [PATCH 2/4] Fixed format --- .../Solution.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt b/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt index cddfa61e3..5b998350b 100644 --- a/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt +++ b/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt @@ -69,7 +69,7 @@ class Solution { if ((mask and (1 shl j)) > 0) { result = max( result, - (dp[mask xor (1 shl j)][j] + distances[i][j]), + dp[mask xor (1 shl j)][j] + distances[i][j], ) } } @@ -79,7 +79,7 @@ class Solution { if ((mask and (1 shl j)) > 0) { result = min( result, - (dp[mask xor (1 shl j)][j] + distances[i][j]), + dp[mask xor (1 shl j)][j] + distances[i][j], ) } } From f5c1c3ffd1010cf59249ee7f9b101688ec33c279 Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sat, 22 Mar 2025 10:02:37 +0200 Subject: [PATCH 3/4] Fixed format --- .../Solution.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt b/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt index 5b998350b..80f97dbc5 100644 --- a/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt +++ b/src/main/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/Solution.kt @@ -1,7 +1,7 @@ package g3201_3300.s3283_maximum_number_of_moves_to_kill_all_pawns // #Hard #Array #Math #Breadth_First_Search #Bit_Manipulation #Bitmask #Game_Theory -// #2025_03_22_Time_119_ms_(100.00%)_Space_66.82_MB_(100.00%) +// #2025_03_22_Time_147_ms_(100.00%)_Space_67.70_MB_(100.00%) import kotlin.math.max import kotlin.math.min @@ -23,20 +23,20 @@ class Solution { var count = n - i val visited = Array(50) { BooleanArray(50) } visited[positions[i][0]][positions[i][1]] = true - val que: java.util.Queue = java.util.ArrayDeque() - que.offer(intArrayOf(positions[i][0], positions[i][1])) + val que: ArrayDeque = ArrayDeque() + que.add(intArrayOf(positions[i][0], positions[i][1])) var steps = 1 - while (!que.isEmpty() && count > 0) { + while (que.isNotEmpty() && count > 0) { var size = que.size while (size-- > 0) { - val cur = que.poll() + val cur = que.removeFirst() val x = cur[0] val y = cur[1] for (d in DIRECTIONS) { val nx = x + d[0] val ny = y + d[1] if (0 <= nx && nx < 50 && 0 <= ny && ny < 50 && !visited[nx][ny]) { - que.offer(intArrayOf(nx, ny)) + que.add(intArrayOf(nx, ny)) visited[nx][ny] = true val j = pos[nx][ny] if (j > i) { From 8478210378defdd732685e968d9a20ccfec6f65f Mon Sep 17 00:00:00 2001 From: Valentyn Kolesnikov Date: Sat, 22 Mar 2025 10:12:49 +0200 Subject: [PATCH 4/4] Added tests --- .../SolutionTest.kt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/src/test/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/SolutionTest.kt b/src/test/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/SolutionTest.kt index d4182a72a..b35ae6477 100644 --- a/src/test/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/SolutionTest.kt +++ b/src/test/kotlin/g3201_3300/s3283_maximum_number_of_moves_to_kill_all_pawns/SolutionTest.kt @@ -36,4 +36,37 @@ internal class SolutionTest { equalTo(3), ) } + + @Test + fun maxMoves4() { + assertThat( + Solution().maxMoves(0, 0, arrayOf()), + equalTo(0), + ) + } + + @Test + fun maxMoves5() { + assertThat( + Solution().maxMoves(49, 49, arrayOf(intArrayOf(48, 48))), + equalTo(4), + ) + } + + @Test + fun maxMoves6() { + assertThat( + Solution().maxMoves(1, 1, arrayOf(intArrayOf(2, 2), intArrayOf(2, 2), intArrayOf(3, 3))), + equalTo(6), + ) + } + + @Test + fun maxMoves7() { + val positions = Array(50) { intArrayOf(it, it) } + assertThat( + Solution().maxMoves(0, 0, positions), + equalTo(266), + ) + } }