学习笔记-汉诺塔问题

在学习MOOC上嵩天老师讲解的Python语言程序设计中老师在讲解递归用法的时候提到了汉诺塔问题;

这个问题我迟迟难以明白,困扰很久,在多方面资料的搜寻下,终于理解,问题分析思路如下:

  • 首先我们需要理解汉诺塔问题是什么?

有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个黄金圆盘。

游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。

操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。

引用于百度百科

  • 如何理解递归? 

在课程中老师讲到递归的定义时,通过类似的数学归纳法(一种数学证明方法)来理解递归;

初中我们都学过数学归纳法,比如我们证明一个定理成立的时候,一般我们采用数学归纳法可以这样证明:

首先证明当N=0的时候,某一个命题成立

接下来假设当N=K时命题成立

进一步证明当N=K+1时,命题也成立

如果这两个步骤都是对的,那我们就能证明某一个命题成立。

这是数学归纳法对递归的一种使用,也可以理解为是数学归纳法思维在编程中的一种体现。

  • 如何使用递归来解决汉诺塔问题?

1,首先需要明确基例链条,然后采用函数+分支语句的写法来完成代码编写。

2,虽然我们需要移动很多圆盘但是我们可以抽象理解,只将n个圆盘化解为n-1个圆盘的搬运,我们只知道递归过程,只关心递归链条,我们只关心当圆盘数量为n的时候,他怎么拆解为当前nn-1当前之间的一个关系,至于n-1下面怎么去做,我们不需要关心他。 

下面给出代码进行分析(附上汉诺塔小游戏辅助理解)

count = 0  #设置一个计数变量count
def hanoi(n, src, mid, dst):
    global count  #将变量声明为全局变量

设置一个计数变量count,并利用保留字globalcount变量在函数中变成全局变量,防止在每次调用时候初值被清零。

再定义四个参数,分别为圆盘的数量n,源头柱子src,过渡柱子mid,目的柱子dst。这里因为方便对应ABC三根柱子所以将老师的参数mid和dst互换位置。

count = 0  #设置一个计数变量count
def hanoi(n, src, mid, dst):
    global count  #将变量声明为全局变量
    if n == 1:
        print("{}:{}->{}".format(1, src, dst))  #打印A柱到C柱过程
        count += 1

用if分支语句先判断基例n=1时相应的变化过程,此时只需要打印出srcA柱)到dstC柱)的这一个过程,过程用到format方法,使用模板"{}:{}->{}"格式化,再用复合赋值运算符表示变量count的连加计数方法。

count = 0  #设置一个计数变量count
def hanoi(n, src, mid, dst):
    global count  #将变量声明为全局变量
    if n == 1:
        print("{}:{}->{}".format(1, src, dst))  #打印A柱到C柱过程
        count += 1
    else:
        hanoi(n - 1, src, dst, mid)  #A柱上n-1到B柱利用C柱过渡的过程
        print("{}:{}->{}".format(n, src, dst))  #打印A柱剩余n到C柱的过程
        count += 1
        hanoi(n - 1, mid, src, dst)  #B柱上n-1到C柱利用A柱过渡的过程

接着我们判断链条,其中nn-1的关系在汉诺塔问题中可以参考图解汉诺塔

这样既然是n个圆盘,从A搬到C,我们可以将n个圆盘中的n-1个圆盘,先从A搬到B,这样的话呢,A柱子中就剩下了最后一个圆盘,我们将最后一个圆盘直接搬到C,然后再将B柱子中的n-1个圆盘挪到C柱子上,这样就实现了A柱子的所有圆盘,向C柱子的一个搬运过程。

count = 0  #设置一个计数变量count
def hanoi(n, src, mid, dst):
    global count  #将变量声明为全局变量
    if n == 1:
        print("{}:{}->{}".format(1, src, dst))  #打印A柱到C柱过程
        count += 1
    else:
        hanoi(n - 1, src, dst, mid)  #A柱上n-1到B柱利用C柱过渡的过程
        print("{}:{}->{}".format(n, src, dst))  #打印A柱剩余n到C柱的过程
        count += 1
        hanoi(n - 1, mid, src, dst)  #B柱上n-1到C柱利用A柱过渡的过程
hanoi(3, 'A', 'B', 'C')
print(count)

接着我们打印出来3个圆盘的过程和次数。

  • 最终代码
count = 0  # 设置一个计数变量count


def hanoi(n, src, mid, dst):
    global count  # 将变量声明为全局变量
    if n == 1:
        print("{}:{}->{}".format(1, src, dst))  # 打印A柱到C柱过程
        count += 1
    else:
        hanoi(n - 1, src, dst, mid)  # A柱上n-1到B柱利用C柱过渡的过程
        print("{}:{}->{}".format(n, src, dst))  # 打印A柱剩余n到C柱的过程
        count += 1
        hanoi(n - 1, mid, src, dst)  # B柱上n-1到C柱利用A柱过渡的过程


hanoi(3, 'A', 'B', 'C')
print(count)

 

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值