백준 9019 DSLR (Java)

배인성·2022년 4월 13일
0

백준

목록 보기
17/22
post-thumbnail

링크

문제 링크

문제 설명

네 개의 명령어 D, S, L, R 을 이용하는 간단한 계산기가 있다. 이 계산기에는 레지스터가 하나 있는데, 이 레지스터에는 0 이상 10,000 미만의 십진수를 저장할 수 있다. 각 명령어는 이 레지스터에 저장된 n을 다음과 같이 변환한다. n의 네 자릿수를 d1, d2, d3, d4라고 하자(즉 n = ((d1 × 10 + d2) × 10 + d3) × 10 + d4라고 하자)

  • D: D 는 n을 두 배로 바꾼다. 결과 값이 9999 보다 큰 경우에는 10000 으로 나눈 나머지를 취한다. 그 결과 값(2n mod 10000)을 레지스터에 저장한다.
  • S: S 는 n에서 1 을 뺀 결과 n-1을 레지스터에 저장한다. n이 0 이라면 9999 가 대신 레지스터에 저장된다.
  • L: L 은 n의 각 자릿수를 왼편으로 회전시켜 그 결과를 레지스터에 저장한다. 이 연산이 끝나면 레지스터에 저장된 네 자릿수는 왼편부터 d2, d3, d4, d1이 된다.
  • R: R 은 n의 각 자릿수를 오른편으로 회전시켜 그 결과를 레지스터에 저장한다. 이 연산이 끝나면 레지스터에 저장된 네 자릿수는 왼편부터 d4, d1, d2, d3이 된다.
    위에서 언급한 것처럼, L 과 R 명령어는 십진 자릿수를 가정하고 연산을 수행한다. 예를 들어서 n = 1234 라면 여기에 L 을 적용하면 2341 이 되고 R 을 적용하면 4123 이 된다.

여러분이 작성할 프로그램은 주어진 서로 다른 두 정수 A와 B(A ≠ B)에 대하여 A를 B로 바꾸는 최소한의 명령어를 생성하는 프로그램이다. 예를 들어서 A = 1234, B = 3412 라면 다음과 같이 두 개의 명령어를 적용하면 A를 B로 변환할 수 있다.

  • 1234 →L 2341 →L 3412
  • 1234 →R 4123 →R 3412

따라서 여러분의 프로그램은 이 경우에 LL 이나 RR 을 출력해야 한다.

n의 자릿수로 0 이 포함된 경우에 주의해야 한다. 예를 들어서 1000 에 L 을 적용하면 0001 이 되므로 결과는 1 이 된다. 그러나 R 을 적용하면 0100 이 되므로 결과는 100 이 된다.

입력

프로그램 입력은 T 개의 테스트 케이스로 구성된다. 테스트 케이스 개수 T 는 입력의 첫 줄에 주어진다. 각 테스트 케이스로는 두 개의 정수 A와 B(A ≠ B)가 공백으로 분리되어 차례로 주어지는데 A는 레지스터의 초기 값을 나타내고 B는 최종 값을 나타낸다. A 와 B는 모두 0 이상 10,000 미만이다.

출력

A에서 B로 변환하기 위해 필요한 최소한의 명령어 나열을 출력한다. 가능한 명령어 나열이 여러가지면, 아무거나 출력한다.

입출력 예제

풀이

  1. 결국에 한칸 한칸 전진해나가면서 최단거리를 재는 것이라 생각해서 BFS로 풀었다.
  2. visited로 방문 체크 해주면서 진행하자.
  3. 그리고 bfs가 끝나고 q를 clear 해주지 않으면 메모리 초과인 것을 주의하자.

백준 문제는 역시 해석 싸움인가 싶다..

나는 이 문제 설명에 하나가 더 추가되어야 한다고 생각했다.

123이 L을 하면 231이 아닌 1230, R을 하면 321이 아닌 3021이 되는 것..

이게 L과 R 명령어의 핵심인데 이거를 너무 희미하게 설명한 느낌이 없지않아 있는 것 같다 ㅠ

저걸 구현하고 나니까 바로 문제가 풀렸다!

근데 시간제한을 이제 보니까 6초네?ㅋㅋㅋ 이런 문제 처음본당,,

코드

import java.util.*;
class Class {
	String now;
	String command;

	Class(String now, String command) {
		this.now = now;
		this.command = command;
	}
}

public class Main {
	static boolean[] visited;
	//1000 * d1 + 100 * d2 + 10 * d3 + d4
	public static int getl(int d1, int d2, int d3, int d4) {
		return 1000 * d2 + 100 * d3 + 10 * d4 + d1;
	}
	public static int getr(int d1, int d2, int d3, int d4) {
		return 1000 * d4 + 100 * d1 + 10 * d2 + d3;
	}	
	public static void bfs(String start, String end) {
		Queue<Class> q = new LinkedList<>();
		q.add(new Class(start, ""));
		visited = new boolean[10000];
		visited[Integer.parseInt(start)] = true;
		while (!q.isEmpty()) {
			Class c = q.poll();
			if (c.now.equals(end)) {
				System.out.println(c.command);
				return;
			}
			// D
			int d = Integer.parseInt(c.now);
			if (!visited[(d * 2) % 10000]) {
				visited[(d * 2) % 10000] = true;
				q.add(new Class(Integer.toString((d * 2) % 10000), c.command + "D"));
			}
			// S
			int s = Integer.parseInt(c.now);
			if (s > 0)
				s--;
			else
				s = 9999;
			if (!visited[s]) {
				visited[s] = true;
				q.add(new Class(Integer.toString(s), c.command + "S"));
			}
			// L R
			int lr = Integer.parseInt(c.now);
			int d1 = lr / 1000;
			lr %= 1000;
			int d2 = lr / 100;
			lr %= 100;
			int d3 = lr / 10;
			int d4 = lr % 10;
			int l = getl(d1,d2,d3,d4);
			int r = getr(d1,d2,d3,d4);
			if(!visited[l])
			{
				visited[l] = true;
				q.add(new Class(Integer.toString(l), c.command + "L"));
			}
			if(!visited[r]) {
				visited[r] = true;
				q.add(new Class(Integer.toString(r), c.command + "R"));				
			}
		}
		q.clear();
	}
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int T = sc.nextInt();
		sc.nextLine();
		while (T-- > 0) {
			String s = sc.nextLine();
			String[] stend = s.split(" ");
			bfs(stend[0], stend[1]);
		}
	}
}

추가

아 그리고 이거 입력받을때ㅜㅜ

int를 입력받고 sc.nextLine으로 개행해주어야지 입력이 제대로 된다.

자꾸 이상하게 split가 안되길래 원인을 또 한참동안 찾았다... ㅋㅋㅋ

profile
부지런히 살자!!

0개의 댓글

관련 채용 정보