D - カード取りゲーム / Card Taking Game 解説 by admin
gemini-3.5-flash-thinkingOverview
This problem asks you to find the final score of a game where two players each act optimally. By leveraging the property that the remaining cards always form a contiguous subarray, we can solve this using interval DP (dynamic programming).
Analysis
Properties of the Game and Approach
In games where two players act optimally with respect to their own objectives (two-player zero-sum finite deterministic perfect information games), backward induction (minimax method) is effective — reasoning from the final state (end of game) backward to determine what happens when both players play optimally.
Moreover, the operation of removing a card can only be performed from the “left end” or the “right end.” Therefore, at any point during the game, the remaining cards always form a contiguous subarray of the original sequence.
Thus, we define the game state as “the state where cards from the \(i\)-th to the \(j\)-th (from the left) remain,” and consider an interval DP that manages the score obtainable from this state until the end of the game.
Determining Whose Turn It Is
Let \(len\) be the number of remaining cards. Since the total number of cards at the start of the game is \(N\), the number of cards removed so far is \(N - len\). Since the first player (Takahashi) and second player alternate removing one card at a time, we can determine whose turn it is based on the number of cards removed so far.
- When \((N - len) \pmod 2 == 0\): Takahashi’s turn
- Takahashi wants to maximize the score, so he chooses the transition that yields a larger value (\(\max\)).
- When \((N - len) \pmod 2 \neq 0\): Aoki’s turn
- Aoki wants to minimize the score, so he chooses the transition that yields a smaller value (\(\min\)).
Memory Optimization (Reduction to 1D DP)
If we naively maintain a 2D array dp[l][r] (the score when the interval \([l, r]\) remains), the space complexity becomes \(O(N^2)\). When \(N = 3000\), this may exceed the memory limit.
However, to compute states of length \(len\), we only need to know the states of length \(len - 1\). Therefore, by updating the array in order of increasing interval length (from \(1\) to \(N\)), we can reduce the stored data to a single 1D array dp (space complexity \(O(N)\)).
Algorithm
- Initialization:
- When
length = 1, only one card remains. The score in this case is the number written on the card itself, so we initialize the DP array asdp = A.
- When
- Transitions:
- We update the DP array by incrementing
lengthfrom \(2\) to \(N\) by \(1\). - From an interval \([i, i + \text{length} - 1]\) of length
length, the two reachable states are:- If the left end is removed: transition to the interval \([i + 1, i + \text{length} - 1]\) of length
length - 1. - If the right end is removed: transition to the interval \([i, i + \text{length} - 2]\) of length
length - 1.
- If the left end is removed: transition to the interval \([i + 1, i + \text{length} - 1]\) of length
- Depending on whose turn it is, the next state is determined as follows:
- Takahashi’s turn: \(\max(\text{result of removing left end}, \text{result of removing right end})\)
- Aoki’s turn: \(\min(\text{result of removing left end}, \text{result of removing right end})\)
- We update the DP array by incrementing
- Output the answer:
- Once the update is complete up to
length = N,dpstores the score for the interval of length \(N\) (i.e., the initial state where all cards remain). The answer isdp[0].
- Once the update is complete up to
Complexity
- Time complexity: \(O(N^2)\)
- The outer loop (interval length \(len\)) runs \(N\) times, and the inner loop (starting position \(i\) of each interval) runs at most \(N\) times, so the overall complexity is \(O(N^2)\). When \(N = 3000\), the number of operations inside the loop is approximately \(4.5 \times 10^6\), which is well within the time limit.
- Space complexity: \(O(N)\)
- Since we only maintain a single 1D array of size \(N\), the memory usage is kept extremely small.
Implementation Notes
Smart transitions using the
zipfunction:- Each element of
dprepresents the result for an interval of lengthlength - 1. - By using
zip(dp, dp[1:]), we can easily create pairs of two adjacent intervals (“result of removing the right end” and “result of removing the left end”) and compute the results for the next lengthlengthall at once.
- Each element of
Optimization in Python:
In Python, calling the built-in
max(x, y)ormin(x, y)functions many times inside a loop becomes slow due to function call overhead.In the code, we use ternary expressions like
x if x > y else yto improve execution speed.Source Code
import sys
def solve():
input = sys.stdin.read
data = input().split()
if not data:
return
N = int(data[0])
A = [int(x) for x in data[1:]]
dp = A
for length in range(2, N + 1):
if (N - length) % 2 == 0:
dp = [x if x > y else y for x, y in zip(dp, dp[1:])]
else:
dp = [x if x < y else y for x, y in zip(dp, dp[1:])]
print(dp[0])
if __name__ == '__main__':
solve()
This editorial was generated by gemini-3.5-flash-thinking.
投稿日時:
最終更新: