KDHzoot's Github

Code for study, project, etc

자세히보기

알고리즘/PS

[백준 11729] 하노이 탑 이동 순서

kdhzoot 2020. 7. 6. 13:13

문제 링크 : https://www.acmicpc.net/problem/11729

 

11729번: 하노이 탑 이동 순서

세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로

www.acmicpc.net

 

n층 탑이 1에서 3으로 가기 위한 이동 횟수를 $F_n$이라고 하자

 

n층의 탑을 1에서 3으로 옮기는 순서는 다음과 같다.

 

 

n-1층의 탑을 1에서 2로 옮긴다

 

n번째 블럭을 1에서 3으로 옮긴다

 

2로 옮긴 n-1층의 탑을 2에서 3으로 옮긴다.

 

 

결국 아래와 같은 식이 성립한다.

 

$$F_n = 2*F_{n-1}+1$$

 

따라서 $F_n$은 $O(n)$안에 구할 수 있다.

 


 

위에 굵은 글씨로 되어있듯이 n층을 옮기는 작업은 n-1층을 옮기는 문제로 부분화할 수 있다.

 

따라서 n-1층을 옮기는 문제는 n-2층을 옮기는 문제로

 

n-2층을 옮기는 문제는 n-3층을 옮기는 문제로

 

계속 내려가다보면 1층을 옮기는 문제, 블럭 하나만 옮기면 되는 문제로 부분화할 수 있다.

 

이는 재귀함수를 통해 구현할 수 있다.

 


 

여기서 문제는 n-1층의 탑을 어디서(from) 어디로(to) 옮기는가이다.

 

from, to를 제외한 남는 공간 res라고 하자.

 

만약 n층을 탑을 옮긴다면

 

n-1층의 탑을 from에서 res로 옮긴다

 

n번째 블럭을 from에서 to로 옮긴다

 

res로 옮긴 n-1층의 탑을 res에서 to로 옮긴다.

 

결국 n-1층의 탑을 옮기는 문제에서는 n층 탑의 res가 to가 되고 to가 res가 된다.

 

다시 원래 위치로 옮기는 문제도 같은 방법으로 다뤄줄 수 있다.

 


 

코드를 읽고 설명을 읽는 것이 더 이해하기 쉬울 것이다.

 

#include <iostream>
#define n_ 200
using namespace std;

void rec(int t, int from, int to, int tmp) {
	if (t == 1) {
		printf("%d %d\n", from, to);
		return;
	}
	rec(t - 1, from, tmp, to);
	printf("%d %d\n", from, to);
	rec(t - 1, tmp, to, from);
}

int main(void) {
	int n;
	cin >> n;

	long long cnt = 1;
	for (int i = 1; i < n; i++) {
		cnt = cnt * 2 + 1;
	}
	cout << cnt << endl;
	rec(n, 1, 3, 2);
	return 0;
}

'알고리즘 > PS' 카테고리의 다른 글

[백준 3036] 링  (0) 2020.07.06
[백준 9613] GCD 합  (0) 2020.07.06
[백준 14650] 걷다보니 신천역 삼 (Small)  (0) 2020.07.05
[백준 1735] 분수 합  (0) 2020.07.05
[백준 14442] 벽 부수고 이동하기 2  (0) 2018.07.23