https://www.acmicpc.net/problem/15500
15500번: 이상한 하노이 탑
첫 번째 줄에 원판을 옮긴 횟수 K (0 ≤ K ≤ 12345) 를 출력한다. 다음 K 개 줄에 걸쳐 A B (1 ≤ A, B ≤ 3) 를 출력하는데 A 번째 장대 맨위에 있는 원판 하나를 B 번째 장대 맨위로 옮긴다는 뜻이다.
www.acmicpc.net
어느 기둥에 있는 원판 N을 3번 기둥에 옮기기 위해선, 원판 N 위에 있는 다른 원판을 모두 3번 기둥이 아닌 다른 기둥으로 치운 뒤 원판 N을 3번 기둥으로 옮겨야 한다. 이 과정을 가장 큰 원판부터 차례로 진행하면 이상한 하노이 탑 문제를 해결할 수 있다.
#include <cstdio>
#define MAX_N 123
#define MAX_K 12345
// str에 원판 하나를 from에서 to로 옮겼음을 표시
void move(char *str, int from, int to) {
str[0] = from;
str[1] = to;
}
int main() {
// pos[i]: i번 원판이 있는 기둥, p: 2번 기둥으로 옮길 원판이 있는 기둥
bool pos[MAX_N + 1] = { 0, }, p;
// 원판을 옮긴 기록을 저장할 공간
char str[MAX_K][2] = { "", };
// N: 원판의 개수, K: 원판을 옮긴 횟수
// a[i][j]: i번 기둥에서 밑에서부터 j번째에 있는 원판
// len[i]: i번 기둥에 있는 원판의 수
int N, K = 0, a[2][MAX_N + 1] = {{ 0, }}, len[2] = { 0, };
// 문제의 조건을 입력받는다
scanf("%d", &N);
for (int i = 0; i < N; i++) scanf("%d", a[0] + i);
// 0번 기둥의 길이를 N으로 정한 뒤
len[0] = N;
// 원판을 크기의 내림차순으로 2번 기둥으로 이동
for (; N; N--) {
// N번 원판이 있는 기둥을 p에 저장한 뒤
p = pos[N];
// 해당 기둥에서 N번 원판을 찾을 때까지
while (len[p] && a[p][--len[p]] != N) {
// p번 기둥에서 !p번 기둥으로 원판을 옮긴 뒤 이를 pos와 str에 표시
a[!p][len[!p]] = a[p][len[p]];
pos[a[!p][len[!p]++]] = !p;
move(str[K++], p, !p);
}
// p번 기둥에서 N번 원판을 2번 기둥으로 이동
move(str[K++], p, 2);
}
// 원판을 옮긴 횟수와 각 원판을 옮긴 기록을 문제의 조건에 맞게 출력
printf("%d\n", K);
for (int i = 0; i < K; i++) printf("%d %d\n", ++str[i][0], ++str[i][1]);
return 0;
}
'알고리즘 > 문제 풀이' 카테고리의 다른 글
15596번: 정수 N개의 합 (0) | 2022.01.12 |
---|---|
15552번: 빠른 A+B (0) | 2022.01.12 |
15483번: 최소 편집 (0) | 2022.01.11 |
15353번: 큰 수 A+B (2) (0) | 2022.01.11 |
14938번: 서강그라운드 (0) | 2022.01.11 |