백준

백준 2840: 행운의 바퀴(java)

unhyepnhj 2024. 7. 18. 17:41

문제


풀이

 

이전의 유사한 유형과 마찬가지로 덱을 사용해 풀이했다. BufferedReader와 StringTokenizer를 이용하여 입력받고 분리하는 과정은 생략하도록 하겠다.

Deque<Character> wheel=new LinkedList<>();
for(int i=0; i<N; i++) {
	wheel.add('?');
}

바퀴의 문자들을 저장할 덱 wheel을 선언해 주고, N개의 '?'들을 초깃값으로 삽입한다. '?'으로 초기화하면 후에 바퀴를 돌리며 한 번도 방문되지 않은 값을 '?'로 따로 설정할 필요가 없다. 

 

이후 회전할 바퀴 수와 입력 문자를 저장할 rotate와 character 변수를 각각 만들어 준다. 이때 N+x바퀴를 돌리는 것은 x바퀴를 돌리는 것과 동일하므로 rotate = (입력값)%N 이다.

for(int j=0; j<rotate; j++) {	//회전 구현
	wheel.addFirst(wheel.removeLast());
}

rotate번째 칸 바로 앞의 칸까지의 값을 덱의 반대편으로 보내는 연산을 통해 바퀴의 회전을 구현했다.

char current=wheel.getFirst();	//적혀 있는 문자
			
if(wheel.contains(character) && current!=character) {
		//입력값과 동일한 문자가 덱에 이미 존재하고 그 문자가 다른 칸에 있을 때
		System.out.println('!');
		return;
}
			
if(current!='?') {	//이미 방문된 칸일 때
		if(current!=character) {	//입력값과 적혀 있는 값이 다르면
			System.out.println("!");
			return;
		}
		else	//입력값과 적혀 있는 값이 같으면
			continue;
}
else {
	//처음 오는 칸일 때
	wheel.removeFirst();	//기존 ?값 삭제
	wheel.addFirst(character);	//문자 삽입
	}
}

바퀴가 존재하지 않는 경우('!'이 출력되는 경우)는

  1. 서로 다른 칸에 같은 문자가 중복되어 존재할 때

  2. 회전된 칸에 이번에 입력한 문자와 다른 문자가 이미 존재할 때

이 두 경우이므로 if문을 이용해 잘 분리해 주어야 한다. 1, 2번 경우에 해당되지 않는다면 그냥 통과하거나 값을 삽입한다.

모든 경우를 잘 구현하지 않으면 오답이 된다. (1번 케이스를 구현하지 않아 3번 정도 틀린 듯)

 

전체 코드는 아래와 같다.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Deque;
import java.util.LinkedList;
import java.util.StringTokenizer;

public class Main{
	public static void main(String[] args) throws IOException{
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st=new StringTokenizer(br.readLine());
		int N=Integer.parseInt(st.nextToken());
		int K=Integer.parseInt(st.nextToken());
		
		Deque<Character> wheel=new LinkedList<>();
		for(int i=0; i<N; i++) {
			wheel.add('?');
		}
		
		int rotate;
		char character;
		for(int i=0; i<K; i++) {
			st=new StringTokenizer(br.readLine());
			rotate=Integer.parseInt(st.nextToken())%N;
			character=st.nextToken().charAt(0);
			
			for(int j=0; j<rotate; j++) {	//회전 구현
				wheel.addFirst(wheel.removeLast());
			}
			
			char current=wheel.getFirst();	//적혀 있는 문자
			
			if(wheel.contains(character) && current!=character) {
				//입력값과 동일한 문자가 덱에 이미 존재하고 그 문자가 다른 칸에 있을 때
				System.out.println('!');
				return;
			}
			
			if(current!='?') {	//이미 방문된 칸일 때
				if(current!=character) {	//입력값과 적혀 있는 값이 다르면
					System.out.println("!");
					return;
				}
				else	//입력값과 적혀 있는 값이 같으면
					continue;
			}
			else {	//처음 오는 칸일 때
			wheel.removeFirst();	//기존 ?값 삭제
			wheel.addFirst(character);	//문자 삽입
			}
		}
		while(!wheel.isEmpty())
			System.out.print(wheel.remove());
	}
}

 

배열을 이용해서도 풀이할 수 있지만, 배열을 여러 개 선언해야 하고 변수도 많아 그냥 덱을 사용했다.

덱을 사용하면 회전 구현이 용이한 듯