6 초 | 256 MB | 60302 | 14809 | 9491 | 20.877% |
문제
네 개의 명령어 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로 변환하기 위해 필요한 최소한의 명령어 나열을 출력한다. 가능한 명령어 나열이 여러가지면, 아무거나 출력한다.
문제에 대한 이해
문제를 처음 보았을 때, 문자열을 이용한 브루트포스 알고리즘이라고 생각했다. 하지만 문제를 3번쯤 틀렸을 때, 문제에 대한 접근성이 잘못되었다는 것을 인지하고, 다른 분들의 풀이를 참조하였다.
https://girawhale.tistory.com/15
어떻게 풀 것인가?
BFS 관련된 문제였다. 주어진 수에 따라 boolean[] visited 과 Queue를 이용하였다.
Queue에 초기 Register를 push하고 반복을 돌며 같은 숫자를 반복하지 않도록 하기 위해 visited[10000] 배열을 사용해 방문한 값을 true로 변경한다.
또한 위 블로그의 풀이를 참조하여 static class Register를 만들었다. 이에 따라 내부의 숫자와 문자열을 저장해주고,
내부 함수에 연산에 따른 함수도 만들었다.
D 연산의 경우 n을 2배한 뒤 값이 9999보다 크다면 %10000 값을 반환하라고 하지만 9999보다 작은 경우에는 %10000을 한다면 원래 값이 반환되므로 num * 2 % 10000을 반환한다.
S 연산의 경우 n == 0일 경우만 9999를 반환하면 되므로, n == 0? 9999 : n - 1을 반환한다.
L 연산의 경우 1000의 자리 숫자를 1의 자리 숫자로 내린 뒤, 나머지 숫자들을 *10한다고 생각하면 쉽다. n % 1000 * 10 + n / 1000
R 연산의 경우 1의 자리 숫자를 1000의 자리 숫자로 올린 뒤, 나머지 숫자들을 / 10하면 결과가 나오게 된다. n % 10 * 1000 + n / 10
시간복잡도
anwer가 주어졌을 때, BFS를 실행할 경우 각 정점(연산에 따른)에 방문횟수에 따라 시간복잡도는 달라지기때문에 O(N)이다.
공간복잡도
주어진 Queue에 따른 각 정점을 담기때문에 공간복잡도 또한 O(N)이다.
풀면서 놓쳤던점
BFS에 대한 이해가 아직 부족한 것 같다.
이 문제를 통해 얻어갈 것
BFS에 대한 새로운 관점과 static class를 이용한 객체 생성에 대해서 공부할 수 있었다.
내 코드
package baekjoon.BJ_9019;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
// 백준알고리즘 9019번 DSLR
public class Main {
static int T, answer, result; // answer = A, result = B
static boolean[] visited;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder sb = new StringBuilder();
T = Integer.parseInt(br.readLine());
for (int i = 0; i < T; i++) {
st = new StringTokenizer(br.readLine());
answer = Integer.parseInt(st.nextToken());
result = Integer.parseInt(st.nextToken());
visited = new boolean[10000];
visited[answer] = true;
Queue<Register> que = new LinkedList<>();
que.add(new Register(answer, ""));
while (!que.isEmpty()) {
Register cur = que.poll();
if (cur.num == result) {
sb.append(cur.command).append("\n");
break;
}
if (!visited[cur.D()]) {
que.add(new Register(cur.D(), cur.command + "D"));
visited[cur.D()] = true;
}
if (!visited[cur.S()]) {
que.add(new Register(cur.S(), cur.command + "S"));
visited[cur.S()] = true;
}
if (!visited[cur.L()]) {
que.add(new Register(cur.L(), cur.command + "L"));
visited[cur.L()] = true;
}
if (!visited[cur.R()]) {
que.add(new Register(cur.R(), cur.command + "R"));
visited[cur.R()] = true;
}
}
}
System.out.println(sb);
}
static class Register {
int num;
String command;
Register(int num, String command) {
this.num = num;
this.command = command;
}
int D() {
return (num * 2) % 10000;
}
int S() {
return num == 0 ? 9999 : num - 1;
}
int L() {
return num % 1000 * 10 + num / 1000;
}
int R() {
return num % 10 * 1000 + num / 10;
}
}
}
'BaekJoon' 카테고리의 다른 글
[백준 알고리즘] 11403번 : 경로 찾기 (JAVA) 문제 풀이 (0) | 2023.02.23 |
---|---|
[백준 알고리즘]1389번 : 케빈 베이컨의 6단계 법칙 (JAVA) 문제 풀이 (0) | 2023.02.23 |
[백준 알고리즘] 10026번 : 적록색약 (JAVA) 문제 풀이 (0) | 2023.02.22 |
[백준 알고리즘] 1644번 : 소수의 연속합 (JAVA) 문제 풀이 (0) | 2023.01.31 |
[백준 알고리즘] 1927번 : 최소 힙 (JAVA) 문제 풀이 (0) | 2023.01.31 |