D - カード取りゲーム / Card Taking Game 解説 by admin
Claude 4.6 Opus (Thinking)Overview
This is a minimax game problem where two players alternately remove cards from either the left or right end of a row of \(N\) cards, and we need to find the score of the last remaining card. It can be solved using interval DP.
Analysis
Key Observations
The game state is determined by the “remaining contiguous interval”: Since only the left or right end can be removed, the remaining cards at any stage always form a contiguous subarray \(A[l..r]\) of the original array.
Whose turn it is can be determined from the interval length: Initially there are \(N\) cards, and it is Takahashi’s turn when there are \(N\) cards. The turn alternates each time a card is removed. In other words, if the number of cards removed so far \(N - (r - l + 1)\) is even, it is Takahashi’s turn; if odd, it is Aoki’s turn.
Interval DP is applicable: The remaining interval \([l, r]\) is the state, and the player whose turn it is optimally chooses between taking the left end (transitioning to \([l+1, r]\)) or taking the right end (transitioning to \([l, r-1]\)).
Comparison with Brute Force Approach
With exhaustive search, there are 2 choices at each turn, and there are \(N-1\) operations, resulting in \(O(2^{N-1})\) complexity. This is far too slow for \(N = 3000\). However, by managing states as intervals \([l, r]\), the number of states is reduced to \(O(N^2)\), allowing for an efficient solution.
Algorithm
We use interval DP.
- State: \(dp[l][r]\) = the final score under optimal play when only cards \(A[l], A[l+1], \ldots, A[r]\) remain
- Base case: When the interval length is 1, \(dp[i][i] = A[i]\) (the last remaining card becomes the score directly)
- Transition: When the interval length is 2 or more
- Number of cards removed: \(\text{removed} = N - (r - l + 1)\)
- If \(\text{removed}\) is even → Takahashi’s turn → \(dp[l][r] = \max(dp[l+1][r],\ dp[l][r-1])\)
- If \(\text{removed}\) is odd → Aoki’s turn → \(dp[l][r] = \min(dp[l+1][r],\ dp[l][r-1])\)
We compute from shorter intervals first, and the final answer is \(dp[0][N-1]\).
Concrete Example
For \(A = [3, 1, 5]\) (\(N=3\)):
- \(dp[0][0]=3,\ dp[1][1]=1,\ dp[2][2]=5\)
- Length 2: removed=1 (Aoki’s turn)
- \(dp[0][1] = \min(dp[1][1], dp[0][0]) = \min(1, 3) = 1\)
- \(dp[1][2] = \min(dp[2][2], dp[1][1]) = \min(5, 1) = 1\)
- Length 3: removed=0 (Takahashi’s turn)
- \(dp[0][2] = \max(dp[1][2], dp[0][1]) = \max(1, 1) = 1\)
The answer is \(1\).
Complexity
- Time complexity: \(O(N^2)\) — there are \(O(N^2)\) intervals, and each state transition is \(O(1)\)
- Space complexity: \(O(N^2)\) — the size of the DP table
Implementation Notes
By computing from shorter intervals first (bottom-up DP), we ensure that transition targets are always already computed.
Turn determination is based on the parity of “number of cards removed = \(N\) - current interval length”. Note that depending on whether \(N\) is odd or even, the turn for each length changes, so it is NOT the case that “odd length always means a specific player’s turn”.
When \(N = 1\), no operations are performed, so we simply output \(A[0]\).
Source Code
import sys
def solve():
input_data = sys.stdin.read().split()
N = int(input_data[0])
A = list(map(int, input_data[1:N+1]))
if N == 1:
print(A[0])
return
# dp[l][r] = the score when the remaining cards are A[l..r]
# The number of cards removed so far is N - (r - l + 1)
# If N - (r-l+1) is even, it's Takahashi's turn (he wants max)
# If N - (r-l+1) is odd, it's Aoki's turn (he wants min)
# Base case: when r - l + 1 == 1, dp[l][r] = A[l]
# We'll iterate by length of interval
dp = [[0] * N for _ in range(N)]
for i in range(N):
dp[i][i] = A[i]
for length in range(2, N + 1):
for l in range(N - length + 1):
r = l + length - 1
removed = N - length
# removed cards so far, next person to act:
# removed == 0 means Takahashi acts (wants to maximize)
if removed % 2 == 0:
# Takahashi's turn: he removes left or right to maximize final score
dp[l][r] = max(dp[l+1][r], dp[l][r-1])
else:
# Aoki's turn: he removes left or right to minimize final score
dp[l][r] = min(dp[l+1][r], dp[l][r-1])
print(dp[0][N-1])
solve()
This editorial was generated by claude4.6opus-thinking.
投稿日時:
最終更新: