汉诺塔问题是程序设计中的经典递归问题。
汉诺塔游戏:有n个盘,A为起始柱,B为借力柱,C为目标柱,n个盘从小到大编号为1、2、3、...、n-1,n,求需要移动的步数最优解F(N).
汉诺塔游戏的规则如下:
1、每次只能移动一个圆盘。
2、圆盘只能放在空柱子上或者比自己大的圆盘上。
3、不能将圆盘放在比自己小的圆盘上。
1、解题思路:
(1)、当n=0,则没有盘,无需移动,故F(n=0)=0
(2)、当n=1,则直接从A柱移动到C柱即可,故F(n=1)=1
(3)、当n=2时,则需要需要的步数F(n=2)=3:
2个盘汉诺塔解法如下图所示:
第1步:将盘1从A柱移动到B柱,需要移动次数为1
第2步:将盘2从A柱移动到C柱,需要移动次数为1
第3步:将盘1从B柱移动到C柱,需要移动次数为1
综上,F(n=2)=1 1 1
2个盘汉诺塔解法
(4)、当有n个盘时,将盘1至盘n-1当作一个整体盘,则问题就转化为整体盘、盘n的两个盘汉诺塔问题了,故需要移动的次数为:F(n)=F(n-1) 1 F(n-1)
n个盘汉诺塔需要移动次数记为F(n),则n个盘汉诺塔解法如下图所示:
第1步:将整体盘(盘1至盘n-1)从A柱移动到B柱,则需要移动次数为F(n-1)
第2步:将单个盘n从A柱移动到C柱,则需要移动次数为1次
第3步:将整体盘(盘1至盘n-1)从B柱移动到C柱,则需要移动次数为F(n-1)
综上:F(n)=F(n-1) 1 F(n-1)=2*F(n-1) 1
n个盘汉诺塔问题(递归求解法)
2、递归求解F(n)
由上面的解题思路,可得n个汉诺塔需移动的步数的递归公式为:F(n)=2F(n-1) 1,其中n>=1,F(0)=0,F(1)=1,经举例发现F(n)=2^n-1(n>=2)。
(1)当n=0时,F(n=0)=0
(2)当n=1时,F(n=1)=1=2^0
(3)当n=2时,F(n=2)=2F(n-1) 1=2F(1) 1=2*1 1=2 1=2^1 2^0=2^2-1=3
(4)当n=3时,F(n=3)=2F(n-1) 1=2F(2) 1=2*(2^1 2^0) 2^0=2^2 2^1 2^0=2^3-1=7
(5)当n=4时,F(n=4)=2F(n-1) 1=2F(3) 1=2*(2^2 2^1 2^0) 2^0=2^3 2^2 2^1 2^0=2^4-1=15
观察上式可得,F(n)=2F(n-1) 1=2^n-1,下面用数学归纳法证明F(n)=2^n-1成立即可。
3、数学归纳法证明F(n)=2^n-1,证明过程如下:
(1)当n=0时,F(n=0)=0=2^0-1
(1)当n=1时,F(n=1)=2F0) 1=2*0 1=1=2^1-1
(2)当n=2时,F(n=2)=2F(n-1) 1=2F(1) 1=2*1 1=3=2^2-1
(3)当n=3时,F(n=3)=2F(n-1) 1=2F(2) 1=2*3 1=7=2^3-1
(4)当n=4时,F(n=4)=2F(n-1) 1=2F(3) 1=2*7 1=15=2^4-1
(5)假设当n=k时,F(n=k)=2F(k-1) 1=2^k-1成立,则只需证明当n=k 1时,等式也成立即可
(6)当n=k 1时,F(n=k 1)=2F(k) 1=2*( 2^k-1 ) 1=2*2^k-2 1=2^(k 1)-1,即当n=k 1时,F(n=k 1)=2^(k 1)-1,等式成立,故F(n)=2^n-1(n>=2)等式成立。
综上:n个盘的汉诺塔需要移动的步数最优解:F(N)=2^n-1.
4、python模拟实现汉诺塔移动过程:
count=0 # 移动次数
# n个盘汉诺塔从A柱移动C柱,B柱为借力柱移动过程模拟,list_start为起始柱的盘子
def hannuota_list(list_start,A_start,B_min,C_end):
global count
n=len(list_start)
if n==0:
print(f'无需移动,已移动次数{count}')
elif n==1:
count=count 1
print(f'第{count}次移动: 盘{list_start[n-1]}:{A_start} --> {C_end}') # 整体盘从起始柱 A_start 移动到目标柱 C_end
else:
list_aa=[list_start[x] for x in range(n-1)] # 盘切分成两部分
#list_bb=list_start[n-1] # 最后一个盘
hannuota_list(list_aa,A_start,C_end,B_min) # 整体盘从起始柱 A_start 移动到 借力柱 B_min,目标柱 C_end 为过渡
count=count 1
print(f'第{count}次移动: 盘{list_start[n-1]}:{A_start} --> {C_end}') # 整体盘从起始柱 A_start 移动到目标柱 C_end
hannuota_list(list_aa,B_min,A_start,C_end) # 整体盘从借力柱 B_min 移动到 目标柱 C_end,起始柱 A_start 为过渡
# 主程序:
if __name__ == '__main__':
n=4
list_a=[x 1 for x in range(n)] # 生成盘号分别为1,2,3,...,n-1,n的盘
print(f'{n}个汉诺塔从上往底部的盘号依次为:{list_a}')
print()
print(f'{n}个盘汉诺塔移动模拟过程如下: ')
count=0
hannuota_list(list_a,A_start='A柱',B_min='B柱',C_end='C柱') # 移动4个盘,起始柱为A柱,目标柱为C柱,借力柱为B柱
运行结果如下:
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved