[백준 9657] 돌 게임 3 (C#, C++) - soo:bak
작성일 :
문제 링크
설명
두 사람이 1개, 3개 또는 4개의 돌을 번갈아 가져갈 수 있을 때, 누가 이기는지 구하는 문제입니다.
돌의 개수 N
이 주어지고, 상근이가 먼저 시작합니다.
돌은 한 번에 1개
, 3개
, 4개
중 원하는 개수만큼 가져갈 수 있으며, 마지막 돌을 가져가는 사람이 승리하게 됩니다.
접근법
현재 돌의 개수에 따라 누가 이기게 되는지를 순차적으로 판단해야 하므로,
각 개수별 결과를 저장하면서 점진적으로 해결하는 방식이 적합합니다.
즉, 돌의 개수가 증가할 때마다 상근이가 이길 수 있는지 여부를 기록하며 계산을 이어갑니다.
이를 위해 남은 돌의 개수
를 기준으로 한 bool
배열을 만들어,
해당 상황에서 상근이가 이길 수 있다면 참
, 그렇지 않으면 거짓
으로 설정합니다.
예를 들어 돌이 i개
남았을 때, 상근이는 1개
, 3개
, 4개
를 가져갈 수 있습니다.
즉, 다음 상태는 각각 i - 1
, i - 3
, i - 4
개의 돌이 남은 상태입니다.
이 중 하나라도 창영이가 이길 수 없는 상태로 만들 수 있다면,
현재 상황은 상근이에게 유리한 상태입니다.
반대로 세 경우 모두 창영이가 이기는 상황이라면, 상근이는 어떤 선택을 하더라도 패배하게 됩니다.
이 논리를 바탕으로 다음과 같은 조건이 도출됩니다:
- 현재 돌이
i개
남았을 때:i - 1
,i - 3
,i - 4
개의 상태가 모두 상근이가 이기는 상태라면,
→ 상근이가 아무리 가져가도 상대가 유리해짐 → 현재는 지는 상태- 이외의 경우 중 하나라도 상대에게 불리한 상태가 있다면,
→ 상근이가 그 쪽으로 넘김 → 현재는 이기는 상태
이를 바탕으로 다음과 같은 점화식을 유도할 수 있습니다:
1
dp[i] = !dp[i - 1] || !dp[i - 3] || !dp[i - 4];
이 방식으로 1
부터 차례대로 돌의 개수에 따라 승패 여부를 채워가면,
마지막 상태에서 상근이의 승패 여부를 결정할 수 있습니다.
Code
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
using System;
class Program {
static void Main() {
int n = int.Parse(Console.ReadLine());
var dp = new bool[1001];
dp[1] = true;
dp[3] = true;
for (int i = 4; i <= n; i++)
dp[i] = !dp[i - 1] || !dp[i - 3] || !dp[i - 4];
Console.WriteLine(dp[n] ? "SK" : "CY");
}
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n; cin >> n;
bool dp[1001] = {false, true, false, true};
for (int i = 4; i <= n; i++)
dp[i] = !dp[i - 1] || !dp[i - 3] || !dp[i - 4];
cout << (dp[n] ? "SK\n" : "CY\n");
return 0;
}