문제 링크
- http://icpc.me/11062
문제 출처
- 2015 ACM-ICPC 대전 인터넷 예선 B번
사용 알고리즘
- 알고리즘 게임
- DP
시간복잡도
- O(n2)
풀이
근우와 명우는 서로 번갈아가면서 카드를 가져가는데, 각 턴마다 왼쪽 혹은 오른쪽 카드 중 하나를 선택해 가져갑니다.
서로 최적의 플레이를 했을 때, 근우가 얼마나 많은 점수를 얻을 수 있는지를 구해야 하는 문제입니다.
가장 기본적으로는 완전 탐색을 돌리면서 근우의 턴에서는 근우의 점수가 최대가 되게, 명우의 턴에서는 근우의 점수가 최소가 되게 플레이하는, 흔히 말해 minimax tree를 그리면 쉽게 해결할 수 있습니다.
int f(int i, int j, bool flag)
를 왼쪽에서 가져간다면 i번째 카드, 오른쪽에서 가져간다면 j번째 카드를 가져가야 하는 상황에서 근우가 얻을 수 있는 최대 점수라고 정의를 합시다. 또한, flag를 이용해 현재 누구의 턴인지 구분을 해줍시다.
완전탐색으로 코드를 짜면 아래와 같습니다.
1 |
|
근우의 턴에서는 근우의 점수를 최대화 시켜야 하고, 명우의 턴에서는 근우의 점수를 최소화 시키는 것이 서로 최적의 플레이를 하는 것입니다.
위 코드로 탐색을 진행하면 O(2n) 복잡도가 나오고, N 범위가 최대 1000이기 때문에 가볍게 시간초과가 나게 됩니다.
만약 i, j, flag의 값이 동일하다면, 그 상황에 대해 언제 계산하든 일정한 값이 나옵니다. 흔히 참조적 투명성이 보장된다고 합니다.
이 특징을 이용해 memoization을 수행해주면 상태 공간은 n*n*2
개이며, 각 상태에 대해 상수시간 안에 해를 구할 수 있습니다. 그러므로 O(n2)만에 문제를 해결할 수 있습니다.
전체 코드
1 |
|