problem solving

백준 16888: 루트 게임

finding wangdo 2023. 2. 24. 15:35

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

 

16888번: 루트 게임

첫째 줄에 테스트 케이스의 개수 T(1 ≤ T ≤ 105)가 주어진다. 둘째 줄부터 T개의 줄에 테스트 케이스가 한 줄에 하나씩 주어지며, N(1 ≤ N ≤ 106)이 주어진다.

www.acmicpc.net

 

게임 이론 문제는 DP로 풀어야 하는 게 있고 규칙성을 찾아야 하는 게 있는데 이건 DP로 푸는 문제다.

 

STEP 0.

 

bool dp[] 배열을 생각해보자

dp[i]에는 내 차례에 숫자가 i일때 내가 이기면 true, 내가 지면 false값을 저장한다.

 

그럼 일단 dp[1]=1, dp[4]=1, dp[9]=1, ...... 모든 제곱수 i에 대해 dp[i]=1이다.

 

STEP 1.

 

i가 제곱수가 아니라면 i 이하 모든 제곱수 j에 대해 dp[i-j]값이 하나라도 0이라면 dp[i]=1이다.

dp[i-j]값이 전부 1이라면 dp[i]는 0이다.

 

상대 차례에 상대가 지는 숫자를 남길 수 있다면 내가 무조건 이기기 때문이다.

 

예를들어 1은 이기는 숫자다.

2는 지는 숫자다. 2 이하 제곱수는 1밖에 없는데 내 차례에 1을 빼면 상대편 차례에 이기는 숫자인 1이 남기 때문이다.

 

그럼 11은 이기는 숫자다.

내 차례에 숫자가 11이라면 나는 9를 빼서 지는 숫자인 2를 상대편에게 남겨줄 수 있기 때문이다.

 

이런 원리로 작은 i부터 시작해서 bottom up 방식으로 DP를 진행한다.

 

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
31
32
33
34
35
36
37
38
39
40
#include <vector>
#include <iostream>
#include<stdbool.h>
 
using namespace std;
 
int main()
{
    int t;
    scanf("%d"&t);
    bool dp[1000005];
    dp[0= 0;
    vector<int> sq;
    int root = 1;
    for (int i = 1;i < 1000001;i++)
    {
        if (root * root == i)
        {
            dp[i] = 1;
            root++;
            sq.push_back(i);
            continue;
        }
        bool x = 0;
        for (auto j : sq)
        {
            x = x || !dp[i - j];
        }
        dp[i] = x;
    }
 
    for (int i = 0;i < t;i++)
    {
        int k;
        scanf("%d"&k);
        printf(dp[k] ? "koosaga\n" : "cubelover\n");
    }
}
 
 
 
 

 

 

'problem solving' 카테고리의 다른 글

백준 3015: 오아시스 재결합  (1) 2023.02.24
백준 3358: Tower of coins  (0) 2023.02.24
백준 24678: 돌무더기 게임 1  (1) 2023.02.24
백준 26156: 나락도 락이다  (3) 2023.02.23
백준 11390: 맛있는 과자  (0) 2023.02.21