티스토리 뷰

 오늘 본 테스트는 내게는 너무나 어려웠다. 시간이 충분하다면 재밌게 풀 수 있는 문제들이었던 것 같은데 시간 분배에 아주 실패했다. 우선 4개의 문제를 둘러보고 먼저 시작할 문제를 골라 시작했는데, 계속 조금만 더 디버깅해보면 될 것 같은 생각에 붙잡고 있다가 시간이 흐르고 다른 문제를 풀기 시작하기에는 시간이 부족할 것 같아서 이 문제라도 풀어내야겠다 하고 끝까지 붙잡고 있다가 시험이 끝난 뒤에도 한참 디버깅하고, 점심 먹고 다시 앉아 함수를 분리해서 코드를 다시 짜보았다.

 입력으로 플레이어 수와 매 턴에 플레이어가 뽑아서 나온 카드가 순서대로 주어진다. 게임에는 A, J, Q, K 네 가지 카드가 사용되고, 각 카드마다 수행 내용이 다른데 마지막에 각 플레이어가 가지게 되는 사탕의 개수를 출력하는 것이 이번 문제다. 카드 A는 카드를 뽑은 사람에게 사탕 하나를 주고, 카드 J는 카드를 뽑은 사람의 양 옆의 사람에게 사탕 하나를 준다. 카드 Q는 플레이어 전부에게 사탕을 하나씩 준다. 그리고 특별한 카드 K는 카드를 뽑은 사람 자신이 팔로우할 플레이어를 한 명 선택할 수 있고, 팔로우는 2명 이상도 가능하다. 팔로우란 플레이어가 사탕을 받았을 때 팔로우하고 있는 사람도 사탕을 받게 되는 것이다. 예를 들어 1번 플레이어가 카드 K를 뽑고 2번 플레이어를 팔로우하기로 했다면 1번 플레이어가 사탕을 받을 때 2번 플레이어도 사탕을 받게 되는 것이다. 따라서 카드 K는 숫자가 이어서 입력으로 주어지는데 팔로우할 플레이어의 번호이고, 플레이어의 번호는 0부터 시작한다. 매 턴에서 받을 수 있는 최대 사탕의 개수는 1개뿐이다.

 자료구조의 특이사항은 매 턴에서 받을 수 있는 사탕의 개수를 한 개로 제한하기 위해 해당 턴에서 사탕을 받았는지 여부를 체크하는 배열과 팔로우 상태를 표현하기 위한 해시 맵을 사용했다. 플레이어의 번호를 Key값으로 사용하고, Value 값으로 해당 플레이어가 팔로우하는 플레이어를 추가할 수 있는 ArrayList를 사용했다.

 

 

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Scanner;
import java.util.StringTokenizer;

public class Main {
	
	static int players;					// 플레이어 수
	static int[] candy;					// 각 플레이어의 사탕 개수
	static HashMap<Integer, ArrayList<Integer>> followers;	// 팔로워 저장
	static boolean[] gotAlready;				// 이번 턴에 사탕을 받았는지 여부
	static int turn;					// 순서

	public static void main(String[] args) throws Exception {
		
//		5
//		A A A A 
		
//		5
//		J A Q A J A

		Scanner sc = new Scanner(System.in);
		
		players = Integer.parseInt(sc.nextLine());
		candy = new int[players];
		gotAlready = new boolean[players];

		followers = new HashMap<>();
		for (int i = 0; i < players; i++) {
			followers.put(i, new ArrayList<Integer>());
		}

		turn = 0;
		String openedCards = sc.nextLine();
		StringTokenizer st = new StringTokenizer(openedCards, " ");
		String card = "";
		
		while (st.hasMoreTokens()) {
			if (turn >= players) turn = 0;
			card = st.nextToken();

			if (card.equals("K")) {
				continue;
			} else if (card.equals("Q")) {
				giveCandyToAll();
			} else if (card.equals("J")) {
				giveCandytoBothSides(turn);
				resetGotAlready();
			} else if (card.equals("A")) {
				giveCandyToPlayer(turn);
				resetGotAlready();
			} else {
				followers.get(turn).add(Integer.parseInt(card));
			}
			turn++;
		}
		
		print();
		
	}
	
	static public void print() {
		for (int i = 0; i < candy.length; i++) {
			if (i == 0)
				System.out.print(candy[i]);
			else
				System.out.print(" " + candy[i]);
		}
	}
	

	static public void giveCandyToPlayer(int currentPlayer) {
		if (!gotAlready[currentPlayer]) {
			candy[currentPlayer]++;
			gotAlready[currentPlayer] = true;
		}
		giveCandyToHisFollowers(currentPlayer);
	}

	static private void giveCandyToHisFollowers(int currentPlayer) {
		if (!followers.get(currentPlayer).isEmpty())
			for (int i = 0; i < followers.get(currentPlayer).size(); i++)
				if (!gotAlready[followers.get(currentPlayer).get(i)]) {
					candy[followers.get(currentPlayer).get(i)]++;
					gotAlready[followers.get(currentPlayer).get(i)] = true;
					giveCandyToHisFollowers(followers.get(currentPlayer).get(i));
				}
	}

	static public void giveCandytoBothSides(int currentPlayer) {
		
		if (currentPlayer <= 0) {
			giveCandyToPlayer(players-1);
			giveCandyToPlayer(currentPlayer+1);
		} else if (currentPlayer == players-1) {
			giveCandyToPlayer(currentPlayer-1);
			giveCandyToPlayer(0);
		} else {
			giveCandyToPlayer(currentPlayer-1);
			giveCandyToPlayer(currentPlayer+1);
		}
	}
	
	static public void giveCandyToAll() {
		for (int i = 0; i < players; i++)
			candy[i]++;
	}

	static public void resetGotAlready() {
		for (int i = 0; i < players; i++)
			if (gotAlready[i])
				gotAlready[i] = false;
	}
		
	static void makeCircle() {

	}
}

 플레이어와 관련된 상태와 행위가 많기 때문에 플레이어 객체를 생성해서 짜보는 것이 좋을 것 같다. 최근에 푼 문제중에 제일 재밌었다. 오늘은 여기까지!

댓글