본문 바로가기

Dot Algo∙ DS/PS

[BOJ] 백준 9658번 돌 게임4 (Java)

#9658 돌 게임4

난이도 : 실버 1

유형 : DP

 

9658번: 돌 게임 4

상근이가 게임을 이기면 SK를, 창영이가 게임을 이기면 CY을 출력한다.

www.acmicpc.net

▸ 문제

돌 게임은 두 명이서 즐기는 재밌는 게임이다.

탁자 위에 돌 N개가 있다. 상근이와 창영이는 턴을 번갈아가면서 돌을 가져가며, 돌은 1개, 3개 또는 4개 가져갈 수 있다. 마지막 돌을 가져가는 사람이 게임을 지게 된다.

두 사람이 완벽하게 게임을 했을 때, 이기는 사람을 구하는 프로그램을 작성하시오. 게임은 상근이가 먼저 시작한다.

 

 입력

첫째 줄에 N이 주어진다. (1 ≤ N ≤ 1000)

 출력

상근이가 게임을 이기면 SK를, 창영이가 게임을 이기면 CY을 출력한다.

 

 

 

문제 풀이  

전형적인 상향식 Bottom-up풀이 문제이다. 규칙을 찾아내어 점화식을 설계해주면 된다.

 

돌 게임3 문제에서 약간 변형이 되었다. 아래의 문제를 풀었다면 이 문제도 쉽게 풀 수 있을 것이다.

 

[BOJ] 백준 9657번 돌 게임3 (JAVA) - DOT CODING

#9657 돌 게임3 난이도 : 실버 3 유형 : DP/ 게임 이론 9657번: 돌 게임 3 상근이가 게임을 이기면 SK를, 창영이가 게임을 이기면 CY을 출력한다. www.acmicpc.net ▸ 문제 돌 게임은 두 명이서 즐기는 재밌

loosie.tistory.com

 

이는 마지막 돌을 가져가면 지는 게임으로 상근이가 무조건 지는 게임을 설계하면 된다.

 

이번에는 창영이를 기준으로 dp[i]=1일 때 창영이가 이긴다고 설정했다.

 

초기값은 다음과 같다.

dp[1] = 1, dp[2] =0, dp[3] =1

 

그 다음은 경우의 수를 따져봐야한다.

dp[4] =0

> dp[i-1] = dp[3] = 1   : 상근 3개 ->  창영 1개

> dp[i-3] = dp[1] = 1  : 상근 1개 -> 창영 3개

> 따라서, 상근이 이길 수 있는 경우가 1개 이상이라도 존재할 때 상근 승리

 

 

돌이 n개 남았을 때, n-1 또는 n-3 또는 n-4개가 남은 시점에서 상근이가 이길 수 있는 경우가 하나라도 존재할 때, dp값은 0이다.

if(dp[i-1] + dp[i-3] + dp[i-4]>0) {
	dp[i] =0;
}

 

Bottom-up 풀이 코드 

import java.io.*;

public class Main {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int n = Integer.parseInt(br.readLine());
		int[] dp = new int[1001];
		
		dp[1] =1;
		dp[2] =0;
		dp[3] =1;
		
		for(int i=4; i<=n; i++) {
			if(dp[i-1] + dp[i-3] + dp[i-4]>0) {
				dp[i] =0;
			}else {
				dp[i] =1;
			}
			
		}
		if(dp[n] ==0) {
			System.out.println("SK");
		}else {
			System.out.println("CY");
		}
		
	}
}

 

 

Top-down 풀이 코드 

점화식을 도출해낸 후 top-down방식으로 재귀호출을 해보니 직관적이여서 이해가 더 잘된다.. 그리고 도저히 점화식이 생각안날 때는 top-down 하향식으로 풀이하다보면 해답이 나올 수도 있다는 것을 생각하자.

import java.io.*;
import java.util.Arrays;

public class Main {

	static int[] dp;
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int n = Integer.parseInt(br.readLine());
		dp = new int[1001];
		
		Arrays.fill(dp, -1);
		
		if(solve(n) ==0) {;
			System.out.println("SK");
		}else {
			System.out.println("CY");
		}
	}
	
	static int solve(int num) {
		if(num <= 0) return 0;
		if(dp[num]!=-1) return dp[num];
		
		int win = solve(num-1) + solve(num-3) + solve(num-4);
		if(win >0) {
			return dp[num] = 0;
		}else {
			return dp[num] = 1;
		}
		
		 
	}
}