알고리즘

[알고리즘] 백준 2840 행운의 바퀴 JAVA 문제 풀이

트리스탄1234 2024. 8. 13. 06:00
728x90
반응형

행운의 바퀴 성공다국어

한국어   
시간 제한메모리 제한제출정답맞힌 사람정답 비율
1 초 128 MB 8712 2211 1574 23.524%

문제

상덕이는 최근에 행운의 바퀴를 구매했다. 상덕이는 바퀴의 각 칸에 알파벳 대문자를 아래 그림과 같이 적었다.

 

바퀴에 같은 글자는 두 번 이상 등장하지 않는다. 또, 바퀴는 시계방향으로만 돌아간다. 바퀴 옆에는 화살표가 있는데, 이 화살표는 항상 한 곳을 가리키고 있으며, 돌아가는 동안 가리키는 글자는 바뀌게 된다. 위의 그림에서는 H를 가리키고 있다.

상덕이는 바퀴를 연속해서 K번 돌릴 것이다. 매번 바퀴를 돌릴 때 마다, 상덕이는 화살표가 가리키는 글자가 변하는 횟수와 어떤 글자에서 회전을 멈추었는지를 종이에 적는다.

희원이는 상덕이가 적어놓은 종이를 발견했다. 그 종이를 바탕으로 상덕이가 바퀴에 적은 알파벳을 알아내려고 한다.

상덕이가 종이에 적어놓은 내용과 바퀴의 칸의 수가 주어졌을 때, 바퀴에 적어놓은 알파벳을 알아내는 프로그램을 작성하시오.

입력

첫째 줄에 바퀴의 칸의 수 N과 상덕이가 바퀴를 돌리는 횟수 K가 주어진다. (2 ≤ N ≤ 25, 1 ≤ K ≤ 100)

다음 줄부터 K줄에는 바퀴를 회전시켰을 때 화살표가 가리키는 글자가 몇 번 바뀌었는지를 나타내는 S와 회전을 멈추었을 때 가리키던 글자가 주어진다. (1 ≤ S ≤ 100)

출력

첫째 줄에 마지막 회전에서 화살표가 가리키는 문자부터 시계방향으로 바퀴에 적어놓은 알파벳을 출력한다. 이때, 어떤 글자인지 결정하지 못하는 칸은 '?'를 출력한다. 만약, 상덕이가 적어놓은 종이에 해당하는 행운의 바퀴가 없다면 "!"를 출력한다. 

예제 입력 1 복사

3 3
1 A
2 B
3 C

예제 출력 1 복사

!

예제 입력 2 복사

5 6
1 A
2 B
5 B
1 C
2 A
2 B

예제 출력 2 복사

B?A?C

예제 입력 3 복사

8 8
4 V
3 I
7 T
7 A
6 R
5 N
1 O
9 H

예제 출력 3 복사

HONITAVR

출처

Contest > Croatian Open Competition in Informatics > COCI 2010/2011 > Contest #7 2번

알고리즘 분류

 
이 문제는 바퀴를 S칸 만큼 돌렸을때 나오는 알파벳을 이용해서 바퀴의 각 칸에 적혀 있는 알파벳을 출력 하는
문제 입니다.
 
입력으로는 우선 바퀴의 칸수인 N을 입력 받고, 바퀴를 몇번 돌린건지를 입력 받는 K
그리고 K번에 걸쳐서 몇칸 움직일 것인지의 수인 S와 S칸을 들렸을때 나오는 문자를 입력을 받는데. 
 
우선 입력 받을 코드를 살펴 보면

public class Main {
	static int N;
	static int K;
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static StringTokenizer st;
	public static void main(String[] args) throws IOException {
		st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		char[] arr = new char[N];
		for(int i =0; i < N; i++) {
			arr[i] = '?';
		}

 
전역 변수로 N,K를 선언을 하고 BufferedReader와 SrinkTokenizer를 이용해서 입력을 받는다. 
그리고 S칸을 움직일때 마다 확인한 문자를 입력할 배열 arr를 선언하고..
 
그 배열을 모두 '?' 로 채워 준다. 
그 배열의 크기는 바퀴의 칸 수만큼 문자를 입력을 받을테니..
 
배열의 Size는 바퀴의 칸 수만큼 으로 만든다. 
그 다음이 배열의 인덱스를 조정해서 해당 문자를 입력 하는 부분이다. 

 
위의 그림은 바퀴를 회전하는 것과 배열의 인덱스를 비교한 것이다. 
화살표를 인덱스로 생각을 해보면 S칸만큼 시계방향으로 옮기면 
 
화살펴 입장에서는 반시계 반향으로 인덱스를 움직이는것과 같다. 
0번 인덱스에 N 이 있는 상태에서 시계 방향으로 4칸을 돌리면 
 
화살표 입장에서는 4칸 만큼 반시계 방향으로 움직인 것이다.
0번 인덱스에서 7번 인덱스, 6번 인덱스, 5번 인덱스,  4번 인덱스로 움직인 것이다. 
 
이걸 수식으로 나타내 보면 아래와 같다. 
((현재 인덱스 - 시계방향으로 움직일 칸수) % N +N) %N을 하면 
 
반시계 방향으로 인덱스를 처리해줄수 있다. 
이걸 코드로 표시를 하면. 

int currentIndex =0;                       // 현재 배열의 인덱스를 0으로 초기화
		for(int i =0; i < K; i++) {        // K번 만큼 바퀴를 돌릴거니까 반복문 사용
			st = new StringTokenizer(br.readLine());
			int step = Integer.parseInt(st.nextToken()); //시계 방향으로 움직일 칸수 입력받고
			char ch = st.nextToken().charAt(0);          //STEP 만큼 움직였을때 나오는 문자를 입력 받고
			int nextIndex = ((currentIndex - step) % N +N) % N; //step만큼 움직였을때의 배열 인덱스를 구하고
			if(arr[nextIndex] == '?') {                 //해당 인덱스가 사용이 되지 않았다면 
				arr[nextIndex] = ch;                    //입력 받은 문자를 배열의 인덱스에 입력하고
			}
			else if(arr[nextIndex] != ch) {            // 사용이 되었고, 입력 받은 문자와 배열의 인덱스에 문자가 틀리면.. .종료 처리
				System.out.println("!");
				return;
			}
			currentIndex = nextIndex;                 // 사용이 되지 않았고 입력 문자를 입력 했으면 이동한 index를 currentIndex로 입력
		}

 
이제 모든 처리는 끝났지만 문제를 다시 자세히 보면 
" 바퀴에 같은 글자는 두 번 이상 등장하지 않는다"라는 문구가 있다. 
 
즉 같은 문자가 배열내에 존재 하는지를 점검 해야 하는 코드가 필요 하다. 

   boolean[] chk = new boolean[26];    // 알파벳의 갯수가 26개 이니 26개의 크기를 갖는 배열을 만든다.
	        for (int i = 0; i < N; i++) {     //바퀴의 칸수 만큼 점검을 할거니까 N번 만큼 반복
	            if (arr[i] == '?') continue;   // arr배열의 i번째가 '?'값이라면 사용되지 않았으니 다음 배열 인덱스로 넘기고
	            if (chk[arr[i] - 'A']) {       // chk배열의 인덱스[arr[i] -'A']가 이미 사용이 되었다면 중복이니까 종료 처리
	                System.out.println("!");
	                return ;
	            }
	            chk[arr[i] - 'A'] = true;     // 아직까지 한번도 나오지 않은 문자라면 해당 문자의 INDEX에 사용되었다고 표시. 
	        }

 
그럼 이제 문제의 요구대로 출력 코드를 생성을 해야 되는데, 
문제의 조건을 보면 
 
" 첫째 줄에 마지막 회전에서 화살표가 가리키는 문자부터 시계방향으로 바퀴에 적어놓은 알파벳을 출력한다. 이때, 어떤 글자인지 결정하지 못하는 칸은 '?'를 출력한다. 만약, 상덕이가 적어놓은 종이에 해당하는 행운의 바퀴가 없다면 "!"를 출력한다. " 이다. 
 
마지막 회전에서 화살표가 표시한 배열의 index는 currentIndex이다. 이를 이용해서 출력문을 작성을 하면. 

for(int i =0; i < N; i++) {
			System.out.print(arr[(currentIndex + i) % N]);
		}
		System.out.println();

 
그럼 이제 전체 코드를 한번에 보면. 

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

public class Main {
	static int N;
	static int K;
	static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
	static StringTokenizer st;
	public static void main(String[] args) throws IOException {
		st = new StringTokenizer(br.readLine());
		N = Integer.parseInt(st.nextToken());
		K = Integer.parseInt(st.nextToken());
		char[] arr = new char[N];
		for(int i =0; i < N; i++) {
			arr[i] = '?';
		}
		int currentIndex =0;
		for(int i =0; i < K; i++) {
			st = new StringTokenizer(br.readLine());
			int step = Integer.parseInt(st.nextToken());
			char ch = st.nextToken().charAt(0);
			int nextIndex = ((currentIndex - step) % N +N) % N;
			if(arr[nextIndex] == '?') {
				arr[nextIndex] = ch;
			}
			else if(arr[nextIndex] != ch) {
				System.out.println("!");
				return;
			}
			currentIndex = nextIndex;
		}
		
		   boolean[] chk = new boolean[26];
	        for (int i = 0; i < N; i++) {
	            if (arr[i] == '?') continue;
	            if (chk[arr[i] - 'A']) {
	                System.out.println("!");
	                return ;
	            }
	            chk[arr[i] - 'A'] = true;
	        }
		for(int i =0; i < N; i++) {
			System.out.print(arr[(currentIndex + i) % N]);
		}
		System.out.println();
	}	
}

 
 

728x90
반응형