하노이의 탑(towers of Hanoi)
작은 원반이 위에, 큰 원반이 아래 위치하도록 쌓은 원반은 3개의 기둥 사이에서 옮기는 문제
원반은 1개씩만 옮길 수 있고 큰 원반에서 작은 원반 순으로 쌓으면서 최소 횟수로 옮겨야 함
하노이의 탑
package ch05_3;
import java.util.Scanner;
// 하노이의 탑
public class Ex01_hanoi {
// no개의 원반을 x번 기둥에서 y번 기둥으로 옮김
static void move(int no, int x, int y) {
if (no > 1) {
move(no - 1, x, 6 - x - y);
}
System.out.printf("원반[%d]을(를) %d번 기둥에서 %d번 기둥으로 옮김\\n", no, x, y);
if (no > 1) {
move(no - 1, 6 - x - y, y);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("하노이의 탑");
System.out.print("원반의 개수: ");
int n = scanner.nextInt();
move(n , 1, 3); // 1번 기둥에 쌓인 n개의 원반을 3번 기둥으로 옮김
}
}
/*
하노이의 탑
원반의 개수: 3
원반[1]을(를) 1번 기둥에서 3번 기둥으로 옮김
원반[2]을(를) 1번 기둥에서 2번 기둥으로 옮김
원반[1]을(를) 3번 기둥에서 2번 기둥으로 옮김
원반[3]을(를) 1번 기둥에서 3번 기둥으로 옮김
원반[1]을(를) 2번 기둥에서 1번 기둥으로 옮김
원반[2]을(를) 2번 기둥에서 3번 기둥으로 옮김
원반[1]을(를) 1번 기둥에서 3번 기둥으로 옮김
*/
메서드 recur3의 비재귀적 표현
package ch05_3;
import java.util.Scanner;
// 메서드 recur3의 비재귀적 표현
public class Ex02_recur3 {
// 메서드 recur의 비재귀적 표현
static void recur3(int n) {
int[] nStk = new int[100];
int[] sStk = new int[100];
int ptr = -1;
int sw = 0;
while (true) {
if (n > 0) {
ptr++;
nStk[ptr] = n;
sStk[ptr] = sw;
if (sw == 0) {
n = n - 1;
} else if (sw == 1) {
n = n - 2;
sw = 0;
}
continue;
}
do {
n = nStk[ptr];
sw = sStk[ptr--] + 1;
if (sw == 2) {
System.out.println(n);
if (ptr < 0) return;
}
} while (sw == 2);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("정수를 입력하세요: ");
int x = scanner.nextInt();
recur3(x);
}
}
/*
정수를 입력하세요: 3
1
2
1
3
*/
하노이의 탑(기둥 이름을 문자열로 출력)
package ch05_3;
import java.util.Scanner;
// 하노이의 탑(기둥 이름을 문자열로 출력)
public class Ex03_hanoiEx {
static String[] name = {"A 기둥", "B 기둥", "C 기둥"};
// 원반을 x기둥에서 y기둥으로 옮김
static void move(int no, int x, int y) {
if (no > 1) {
move(no - 1, x, 6 - x - y);
}
System.out.println("원반[" + no + "]을(를) " + name[x - 1] + "에서 " + name[y - 1] + "으로 옮김");
if (no > 1) {
move(no - 1, 6 - x - y, y);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("하노이의 탑");
System.out.print("원반의 개수: ");
int n = scanner.nextInt();
move(n , 1, 3); // 1번 기둥에 쌓인 n개의 원반을 3번 기둥으로 옮김
}
}
/*
하노이의 탑
원반의 개수: 3
원반[1]을(를) A 기둥에서 C 기둥으로 옮김
원반[2]을(를) A 기둥에서 B 기둥으로 옮김
원반[1]을(를) C 기둥에서 B 기둥으로 옮김
원반[3]을(를) A 기둥에서 C 기둥으로 옮김
원반[1]을(를) B 기둥에서 A 기둥으로 옮김
원반[2]을(를) B 기둥에서 C 기둥으로 옮김
원반[1]을(를) A 기둥에서 C 기둥으로 옮김
*/
하노이의 탑(비재귀적 구현)
package ch05_3;
import java.util.Scanner;
// 하노이의 탑(비재귀적 구현)
public class Ex04_hanoiN {
// 원반을 x기둥에서 y기둥으로 이동
static void move(int no, int x, int y) {
int[] xStk = new int[100];
int[] yStk = new int[100];
int[] sStk = new int[100];
int ptr = 0; // 스택 포인터
int sw = 0;
while (true) {
if (sw == 0 && no > 1) {
xStk[ptr] = x; // x 값 푸시
yStk[ptr] = y; // y값 푸시
sStk[ptr] = sw; // sw값 푸시
ptr++;
no -= 1;
y = 6 - x - y;
continue;
}
System.out.printf("원반[%d]을 %d 기둥에서 %d 기둥으로 이동\\n", no, x, y);
if (sw == 1 && no > 1) {
xStk[ptr] = x;
yStk[ptr] = y;
sStk[ptr] = sw;
ptr++;
no -= 1;
x = 6 - x - y;
if(++sw == 2) sw = 0;
continue;
}
do {
if (ptr-- == 0) return; // 스택이 비어 있으면
x = xStk[ptr]; // 값을 저장하고 있는 x를 팝
y = yStk[ptr]; // 값을 저장하고 있는 y를 팝
sw = sStk[ptr] + 1; // 값을 저장하고 있는 sw을 팝
no++;
} while (sw == 2);
}
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("하노이의 탑");
System.out.print("원반의 개수: ");
int n = scanner.nextInt();
move(n, 1, 3); // 제1기둥에 쌓인 n개를 제3기둥으로 이동
}
}
/*
하노이의 탑
원반의 개수: 3
원반[1]을 1 기둥에서 3 기둥으로 이동
원반[2]을 1 기둥에서 2 기둥으로 이동
원반[1]을 3 기둥에서 2 기둥으로 이동
원반[3]을 1 기둥에서 3 기둥으로 이동
원반[1]을 2 기둥에서 1 기둥으로 이동
원반[2]을 2 기둥에서 3 기둥으로 이동
원반[1]을 1 기둥에서 3 기둥으로 이동
*/
'공부기록 > 알고리즘' 카테고리의 다른 글
Chapter 06-1. 정렬 알고리즘_정렬 알고리즘이란 (0) | 2024.08.16 |
---|---|
Chapter 05-4. 재귀 알고리즘_8퀸 문제 (0) | 2024.08.11 |
Chapter 05-2. 재귀 알고리즘_재귀 알고리즘 분석 (0) | 2024.08.11 |
Chapter 05-1. 재귀 알고리즘_재귀 알고리즘의 기본 (0) | 2024.08.11 |
Chapter 04-2. 스택과 큐_큐란 (0) | 2024.08.04 |
댓글