汉诺塔
汉诺
每次 只 能 移 动一个圆盘;大 盘不能 叠在小 盘上面 。
问:
这里
传说
[编辑]這個
解答
[编辑]如取 N=64,
算法 求 解
[编辑]如此递归
遞迴解
[编辑]public class HW {
public static java.util.Scanner sc = new java.util.Scanner(System.in);
public static void Towers(int n,char a,char b,char c){
if(n==1){
System.out.println("移動 "+n+"從 "+a+"到 "+c);
}
else{
Towers(n-1,a,c,b);
System.out.println("移動 "+n+"從 "+a+"到 "+c);
Towers(n-1,b,a,c);
}
}
public static void main(String[] args) {
int n = sc.nextInt();
Towers(n,'A','B','C');
}
}
以 C++ 语言实现:
#include <iostream>
using namespace std;
void Towers(int n,char a,char b,char c){
if(n==1){
cout<<"Move disk "<<n<<" from"<<a<<" to "<<c<<endl;
}
else{
Towers(n-1,a,c,b);
cout<<"Move disk "<<n<<" from"<<a<<" to "<<c<<endl;
Towers(n-1,b,a,c);
}
}
int main(int argc, char *argv[]) {
int n;
cin>>n;
Towers(n,'A','B','C');
cout<< endl;
}
以 Python 语言实现:
def hanoi(n, a, b, c):
if n == 1:
print(a, '-->', c)
else:
hanoi(n - 1, a, c, b)
hanoi(1 , a, b, c)
hanoi(n - 1, b, a, c)
# 调用
if __name__ == '__main__':
hanoi(5, 'A', 'B', 'C')
以 Erlang 语言
-module(hanoi).
-export([hanoi/1]).
hanoi(N) when N>0 ->
do_hanoi({N, 1, 3}).
do_hanoi({0, _, _}) ->
done;
do_hanoi({1, From, To}) ->
io:format("From ~p, To ~p~n", [From, To]);
do_hanoi({N, From, To}) ->
do_hanoi({N-1, From, by(From, To)}),
do_hanoi({1, From, To}),
do_hanoi({N-1, by(From, To), To}).
by(From, To) ->
[Result|_] = [1, 2, 3] -- [From, To],
Result.
以 Haskell 语言实现:
hanoi :: Integer -> String -> String -> String -> [(String, String)]
hanoi 0 _ _ _ = []
hanoi 1 from _ to = [(from, to)]
hanoi x from buffer to =
hanoi (x-1) from to buffer ++ hanoi 1 from buffer to ++ hanoi (x-1) buffer from to
任意 初 始 結構 (arbitrary initial configuration)的 解法
[编辑]以 Scheme
; Let conf be a list of the positions of the disks in order of increasing size.
; Let the pegs be identified by the numbers 0, 1 and 2.
(define (hanoi conf t)
(let ((c (list->vector conf)))
(define (move h f t)
(vector-set! c h t)
(printf "move disk ~s from peg ~s to peg ~s~n" h f t))
(define (third-peg f t) (- 3 f t))
(define (hanoi h t)
(if (> h 0)
(let ((h (sub1 h)))
(let ((f (vector-ref c h)))
(if (not (= f t))
(let ((r (third-peg f t)))
(hanoi h r)
(move h f t)))
(hanoi h t)))))
(hanoi (vector-length c) t)))
public class Hanoi {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(hanoiFunc(7));
}
public static int hanoiFunc(int i) {
int sum = 0;
if (i == 1) {
sum += i;
}
else {
sum = 2 * hanoiFunc(i - 1) + 1;
}
return sum;
}
}
int conf[HEIGHT]; /* Element conf[d] gives the current position of disk d. */
void move(int d, int t) {
/* move disk d to peg t */
conf[d] = t;
}
void hanoi(int h, int t) {
if (h > 0) {
int f = conf[h-1];
if (f != t) {
int r = 3 - f - t ;
hanoi(h-1, r);
move(h-1, t);
}
hanoi(h-1, t);
}
}
图像解 释
[编辑]现在规定,
对于
-
一个盘子的情况
对于
对于
-
两个盘子
的 汉诺塔
对于 h+1 个盘
这个
-
三个盘子的汉诺塔
- a、b
和 c表示 三 个柱子
- 按照从小
到 大 的 顺序, 从左到 右 地 列 出 的 盘子的 位置 。
如果
就是
-
三个盘子的汉诺塔 -
通路
顺便
也可以得
-
三个盘子的汉诺塔的哈密顿回路
该图较为
- 对于
任意 的 全部 盘子在 一根柱子的情况下,将 所有 盘子移 动到另一个柱子的最短路径只有一个。 - 对于
任意 的 两个盘子分布 情 况之间转换的时候,只 有 一个或者两个不同的最短路径。 - 对于
任意 的 盘子分布 情 况,都 有一 个或者 两个将 所有 盘子移 动到任意 一个柱子上的最长不相交路径。 - 对于
任意 的 两个盘子分布 情 况之间转换的时候,只 有 一个或者两个不同的最长不相交路径。 - 设
是 将 有 个盘子 的 塔 ,将 所有 盘子从一个柱子移动到另一个柱子的非相交路径的数量(一开始盘子都在一个柱子上)。可 以得出 :- N 1 = 2,
- 。
这里
多 塔 汉诺塔 问题
[编辑]在 有 3 个柱子 时,所 需步数 的 公式 较简单,但 对于 4 个柱子 以上 時 ,情 形 複雜 許多 。Frame 及 Stewart在 1941年 時 分別 提出 了 基本 上相 同 的 一 套演算法 [1],Bousch則 在 2014年 證明 了 Frame-Stewart演算 法 在 4個 柱 子 時 就是最 佳 解 [2],但 此演算法 在 5個 柱 子 以上 是 否 是 最 佳 解 仍是未知 。
Frame-Stewart
令 为在有 个柱子 时,移 动n个圆盘到另一 柱 子 上 需要 的 步数 ,则:
- 对于
任 何 移 动方法 ,必定 会 先 将 个圆盘移动到一个中间柱子上,再 将 第 到 第 个圆盘通过剩下 的 个柱子 移 到 目 标柱子 上 ,最 后 将 个在中 间柱子 上 的 圆盘移 动到目 标柱子 上 。这样所 需的操作 步数 为 。 - 进行
最 优化,易 得 : 。
- 对于
流行 文化
[编辑]2011
參 見
[编辑]參考 來 源
[编辑]- ^ Stewart, B.M.; Frame, J.S. Solution to advanced problem 3819. American Mathematical Monthly. March 1941, 48 (3): 216–9. JSTOR 2304268. doi:10.2307/2304268.
- ^ Bousch, T. La quatrieme tour de Hanoi. Bull. Belg. Math. Soc. Simon Stevin. 2014, 21: 895–912.