Notice
Recent Posts
Recent Comments
Link
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

dh-winternagi 님의 블로그

(11062) 카드 게임 본문

백준 (C++)/Solve

(11062) 카드 게임

dh-winternagi 2026. 4. 19. 23:46

https://www.acmicpc.net/problem/11062

단계별로 풀어보기

31단계(동적 계획법 2) 7번째

 

 

 

이것도 정말 어려운 DP문제다. dp를 정의하는 것부터 난관이다.

dp[a][b]를 a번째 카드부터 b번째 카드까지 남았을 때 지금 차례인 사람이 얻을 수 있는 점수의 최대값이라고 하자.

dp[x][x]는 현재 차례인 사람이 그 카드를 가져가고 게임이 끝나므로 x번째 카드의 값과 같다.

dp[x][y] 상태에서, 현재 플레이어는 x번째 카드 또는 y번째 카드를 가져갈 수 있다.

이때 상대방이 얻는 점수는 dp[x+1][y] 또는 dp[x][y-1]이다. 최선의 선택을 한다면 이 값을 최소화할 것이다.

따라서 dp[x][y]= (지금 상태에서 가능한 점수 총합)-min(dp[x+1][y], dp[x][y-1])이다.

지금 상태에서 가능한 점수 총합은 x번째 카드부터 y번째 카드까지 부분합이다.

dp를 현재 차례인 사람이 얻는 점수의 최대값으로 정의했으므로, N의 홀짝 여부에 관계없이 dp[1][N]이 답이다.

 

 

 

#include <iostream>
#include <vector>
using namespace std;

int solve(){
  int n;
  
  cin >> n;
  
  vector<int> s(n+1);
  vector dp(n+1, vector<int>(n+1));
  
  for(int i=1;i<=n;i++){
    cin >> s[i];
    
    dp[i][i]= s[i];
    s[i]+= s[i-1];
  }
  
  for(int i=1;i<n;i++){
    for(int j=1;j+i<=n;j++){
      dp[j][j+i]= s[j+i]-s[j-1]-min(dp[j+1][j+i], dp[j][j+i-1]);
    }
  }
  
  return dp[1][n];
}

int main() 
{
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  cout.tie(NULL);
  
  int T;
  
  cin >> T;
  
  while(T--){
    cout << solve() << "\n";
  }
  
  return 0;
}

'백준 (C++) > Solve' 카테고리의 다른 글

(14002) 가장 긴 증가하는 부분 수열 4  (0) 2026.04.20
(12852) 1로 만들기 2  (0) 2026.04.20
(7579) 앱  (0) 2026.04.19
(2293) 동전 1  (0) 2026.04.19
(2629) 양팔저울  (0) 2026.04.19