It's easy, if you try

[백준/boj] 20923: 숫자 할리갈리게임 (Java) / 덱 / 시뮬레이션 본문

알고리즘/자바(Java)

[백준/boj] 20923: 숫자 할리갈리게임 (Java) / 덱 / 시뮬레이션

s5he2 2021. 3. 4. 21:30
반응형

문제

 

20923번: 숫자 할리갈리 게임

첫째 줄에는 도도와 수연이가 가지는 카드의 개수 $N$($ 1 \leq N \leq 30\,000$)과 게임 진행 횟수 $M$($ 1 \leq M \leq 2\,500\,000$)이 주어진다. 둘째 줄부터 $N$개의 줄에는 띄어쓰기로 구분하여 도도와 수연

www.acmicpc.net

풀이

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

public class Main_BOJ_20923_숫자할리갈리게임 {
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static StringTokenizer st;
	static Deque<Integer> doD = new ArrayDeque<>(), suD = new ArrayDeque<>();
	static ArrayList<Integer> sGround = new ArrayList<>(), dGround = new ArrayList<>();
	static int N, M;

	public static void main(String[] args) throws Exception {
		st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		M = Integer.parseInt(st.nextToken());

		for (int i = 0; i < N; i++) {
			st = new StringTokenizer(br.readLine());
			doD.add(Integer.parseInt(st.nextToken()));
			suD.add(Integer.parseInt(st.nextToken()));
		}

		int dNum, sNum;
		while (M > 0) {
			if (isEmptyDeque())
				return;
			
			dNum = doD.pollLast(); // do 차례
			dGround.add(dNum);

			if (isEmptyDeque())
				return;

			if (dNum == 5) { // do 종
				doGet();
			} else if (sGround.size() > 0 
            	&& dNum + sGround.get(sGround.size() - 1) == 5) { // su 종
				suGet();
			}

			M--;
			if (M == 0) {
				break;
			}

			sNum = suD.pollLast(); // su 차례
			sGround.add(sNum);
			if (sNum == 5) { // do 종
				doGet();
			} else if (dGround.size() > 0 
            	&& sNum + dGround.get(dGround.size() - 1) == 5) { // su 종
				suGet();
			}
			M--;
		}

		if (doD.size() == suD.size()) {
			System.out.println("dosu");
		} else {
			if (doD.size() > suD.size()) {
				System.out.println("do");
			} else {
				System.out.println("su");
			}
		}
	}

	private static boolean isEmptyDeque() {
		if (doD.isEmpty() || suD.isEmpty()) {
			if (doD.size() == 0)
				System.out.println("su");
			else
				System.out.println("do");
			return true;
		}
		return false;
	}

	private static void suGet() {
		while (!dGround.isEmpty()) {
			suD.addFirst(dGround.remove(0));
		}
		while (!sGround.isEmpty()) {
			suD.addFirst(sGround.remove(0));
		}
	}

	private static void doGet() {
		while (!sGround.isEmpty()) {
			doD.addFirst(sGround.remove(0));
		}
		while (!dGround.isEmpty()) {
			doD.addFirst(dGround.remove(0));
		}
	}
}

 

게임 종료 조건

  1. 둘 중 한명의 deque이 비는 경우 : 한 명이 카드를 그라운드에 놓을 때마다, deque가 비었는지 검사(isEmptyDeque())한다.
  2. ★ M번 진행됐을 때 ★: 한 명이 카드를 그라운드에 놓고 종을 칠 수 있는지 조건을 비교(조건 성립 시, 종을 침)하는 과정이 한번이다.

 

카드를 내고, 가져가는 방식

  • 카드를 처음 받아올 때 : deque 의 끝에 더해나간다.
  • deque 맨 위 카드를 그라운드에 놓을 때 : deque의 맨 뒤에서 빼서 (pollLast) ground의 맨 뒤에 더한다. (add)
  • 종을 쳐서 가져갈 때
    1. ★ 상대방 의 ground가 빌 때까지, ground의 맨 밑 카드를 빼와 (remove(0)) 자신의 deque의 맨 아래에 넣는다(addFirst).
    2. 자신의 ground가 빌 때까지, ground의 맨 밑 카드를 빼와(remove(0)) 자신의 deque의 맨 아래에 넣는다(addFirst).

 

반응형
Comments