11729 : 하노이 탑 이동순서#
시간제한 |
메모리제한 |
정답비율 |
---|---|---|
1초 |
256MB |
50.536% |
문제#
세 개의 장대가 있고 첫 번째 장대에는 반경이 서로 다른 n개의 원판이 쌓여 있다. 각 원판은 반경이 큰 순서대로 쌓여있다. 이제 수도승들이 다음 규칙에 따라 첫 번째 장대에서 세 번째 장대로 옮기려 한다.
한 번에 한 개의 원판만을 다른 탑으로 옮길 수 있다. 쌓아 놓은 원판은 항상 위의 것이 아래의 것보다 작아야 한다. 이 작업을 수행하는데 필요한 이동 순서를 출력하는 프로그램을 작성하라. 단, 이동 횟수는 최소가 되어야 한다.
input#
첫째 줄에 첫 번째 장대에 쌓인 원판의 개수 N (1 ≤ N ≤ 20)이 주어진다.
output#
첫째 줄에 옮긴 횟수 K를 출력한다.
두 번째 줄부터 수행 과정을 출력한다. 두 번째 줄부터 K개의 줄에 걸쳐 두 정수 A B를 빈칸을 사이에 두고 출력하는데, 이는 A번째 탑의 가장 위에 있는 원판을 B번째 탑의 가장 위로 옮긴다는 뜻이다.
think#
하노이 탑은 기본적으로 백트레킹 문제이다. 여기서 이동 순서에 대해서 출력을 해야한다. 그런데 이동횟수가 최소가 되어야한다는 조건이 달려있다.
python#
import sys, os
problem_num = "11729"
path = os.getcwd() + f"\\txt\\{problem_num}" + ".txt"
sys.stdin = open(path, "r")
input = sys.stdin.readline
n = int(input())
result = []
def move(start, to):
return [start, to]
def hanoi(n, start, to, via):
if n == 1:
result.append(move(start, to))
else:
hanoi(n - 1, start, via, to)
result.append(move(start, to))
hanoi(n - 1, via, to, start)
return result
answer = hanoi(n, 1, 3, 2)
print(len(answer))
for i in answer:
print(*i)
7
1 3
1 2
3 2
1 3
2 1
2 3
1 3
javascript#
1const problem_num = "11729";
2const path = `${__dirname}\\txt\\${problem_num}.txt`;
3// const path = "/dev/stdin";
4
5const input = require("fs").readFileSync(path, 'utf8').toString().trim().split('\n');
6let currentLine = 0;
7
8function readLine() {
9 return input[currentLine++].split(' ').map(Number);
10}
11
12const n = parseInt(readLine()[0]);
13let moves = [];
14
15function hanoi(n, start, to, via) {
16 if (n == 1) {
17 moves.push(`${start} ${to}`);
18 } else {
19 hanoi(n - 1, start, via, to);
20 moves.push(`${start} ${to}`);
21 hanoi(n - 1, via, to, start)
22 }
23 return moves
24}
25
26let answer = hanoi(n, 1, 3, 2);
27console.log(moves.length);
28console.log(moves.join('\n'));
숫자 하나만을 받으므로 [0] 인덱스 접근
짜피 print해야함으로 `, $ 를 이용해서 변수 받아서 string해주기
java#
1import java.io.*;
2import java.util.*;
3
4public class Main {
5 public static void main(String[] args) throws IOException {
6 String problemNumber = "11729";
7 String path = System.getProperty("user.dir") + "\\scripts\\algorithm\\problem\\txt\\" + problemNumber + ".txt";
8 BufferedReader br = new BufferedReader(new FileReader(path));
9 BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
10 // BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
11 // StringTokenizer st = new StringTokenizer(br.readLine());
12
13 int n = Integer.parseInt(br.readLine());
14 br.close();
15 StringBuilder sb = new StringBuilder();
16 int moveCount = hanoi(n, 1, 2, 3, sb);
17
18 bw.write(moveCount + "\n");
19 bw.write(sb.toString());
20 bw.flush();
21 bw.close();
22 }
23
24 public static int hanoi(int n, int start, int via, int to, StringBuilder sb) {
25 if (n == 1) {
26 sb.append(start).append(" ").append(to).append("\n");
27 return 1;
28 } else {
29 int count1 = hanoi(n - 1, start, to, via, sb);
30 sb.append(start).append(" ").append(to).append("\n");
31 int count2 = hanoi(n - 1, via, start, to, sb);
32 return count1 + count2 + 1;
33 }
34 }
35}
맨처음엔 그냥 하니깐 시간초과가 나옴
System.out
을 사용하면 엄청 느려서 모아놨다가 한번에 출력하는StringBuilder
에 가져다 붙여놨다가 한번에 출력하는 방식으로 해야함.굳이 이렇게까지 불편하게 해야하나 싶음. python은 신이다.
하지만 메모리면에서는 java가 48412kb로 javascript(153640kb), python(123336kb)인 것에 비해서 굉장히 큰 이점이 존재하는 것은 맞는 것으로 보인다.
string에는 append, list에는 add… 정말루다가 너무 헤깔린다.