2022. 5. 8. 18:42ㆍ알고리즘/코딩테스트(백준)
문제
세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로 옮기려 한다.
- 한 번에 한 개의 원판만을 다른 탑으로 옮길 수 있다.
- 쌓아 놓은 원판은 항상 위의 것이 아래의 것보다 작아야 한다.
이 작업을 수행하는데 필요한 이동 순서를 출력하는 프로그램을 작성하라. 단, 이동 횟수는 최소가 되어야 한다.
아래 그림은 원판이 5개인 경우의 예시이다.
입력
첫째 줄에 첫 번째 장대에 쌓인 원판의 개수 N (1 ≤ N ≤ 100)이 주어진다.
출력
첫째 줄에 옮긴 횟수 K를 출력한다.
N이 20 이하인 입력에 대해서는 두 번째 줄부터 수행 과정을 출력한다. 두 번째 줄부터 K개의 줄에 걸쳐 두 정수 A B를 빈칸을 사이에 두고 출력하는데, 이는 A번째 탑의 가장 위에 있는 원판을 B번째 탑의 가장 위로 옮긴다는 뜻이다. N이 20보다 큰 경우에는 과정은 출력할 필요가 없다.
public class No1914 {
static StringBuilder sb;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sb = new StringBuilder();
if(n<=20){
sb.append((int)Math.pow(2, n)- 1).append('\n');
Hanoi(n, 1 ,2 ,3);
}else{
BigInteger b = new BigInteger("1");
for(int i =0; i<n; i++){
b = b.multiply(new BigInteger("2"));
}
b = b.subtract(new BigInteger("1"));
sb.append(b).append('\n');
}
System.out.println(sb);
}
private static void Hanoi(int n, int start, int mid, int to) {
//이동할 원반의 개수가 1개인 경우
if(n == 1){
sb.append(start + " "+ to+'\n');
return;
}
//1번 -> 3번으로 원반을 움직일때, n-1개의 원반을 2번으로 이동
Hanoi(n-1 , start, to , mid);
//마지막 1개의 원반을 1 -> 3번으로 이동
sb.append(start + " " + to + '\n');
//나머지 2에있는 n-1개의 원반을 3번으로 이동
Hanoi(n-1, mid, start , to);
}
}
하노이 탑 이동 규칙은, 작은 원반 위에 더 큰 원반이 올 수 없다는 것이다.
가장 큰(맨 아래에 있는) 원반이 3번으로 이동하기 위해서는, 다른 모든 원반이 2번에 있어야 가능하다.
다음으로, 2번에 있는 n-1개의 원반이 3번으로 이동하면 하노이탑 완성이다.
처음에 n-1개의 원반이 1번에서 2번으로 이동하는 Hanoi(n-1)와, 가장 큰 원반을 3번에 보낸 뒤
2번에 있는 n-1개의 원반을 3번으로 이동하는 Hanoi(n-1)를 적절히 변형해주면 된다.
n이 20보다 큰 경우에는 과정을 생략하고 이동 횟수만 출력하면 된다.
이동횟수는 2^n-1로 문제에서 입력 값으로 ( 1<=n<=100 )가 주어졌다.
long 타입으로 커버할 수 없어 BigInteger 타입을 이용해야 한다.
'알고리즘 > 코딩테스트(백준)' 카테고리의 다른 글
백준 2869: 달팽이는 올라가고 싶다 [Java] - 포포 (0) | 2022.05.28 |
---|---|
백준 10775: 공항 [Java] - 포포 (2) | 2022.05.20 |
백준 1931번: 회의실 배정 (0) | 2022.02.18 |
백준 11047번: 동전 0 (0) | 2022.02.14 |
백준 10845번: 큐 (0) | 2022.02.14 |