人工智能原理实验1(3)——汉诺塔问题

🧡🧡实验内容🧡🧡

汉诺塔问题来自一个古老的传说:在世界刚被创建的时候有一座钻石宝塔(塔A),其上有64个金碟。所有碟子按从大到小的次序从塔底堆放至塔顶。紧挨着这座塔有另外两个钻石宝塔(塔B和塔C)。从世界创始之日起,婆罗门的牧师们就一直在试图把塔A上的碟子移动到塔C上去,其间借助于塔B的帮助。每次只能移动一个碟子,任何时候都不能把一个碟子放在比它小的碟子上面。当牧师们完成任务时,世界末日也就到了。

采用问题归约法把汉诺塔问题分成以下三个步骤实现:

  • 将塔A上的n-1个碟子借助塔C先移到塔B上
  • 把塔A上剩下的一个碟子移到塔C上
  • 把n-1个碟子从塔B借助于塔A移到塔C上

🧡🧡实现🧡🧡

def move(start, end):
    # print(f'{start}->{end}')
    global cnt
    cnt += 1

def dfs(n, a, b, c):  # 把 n个a 通过b 移动到c
    if n == 1:
        move(a, c)
    else:
        dfs(n - 1, a, c, b)
        move(a, c)
        dfs(n - 1, b, a, c)

import time
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 为了支持中文字体
if __name__ == "__main__":
    n=list(range(15,23)) # 盘子数
    t=[] # 运行时间
    m=[] # 递归调用次数
    start=time.time()
    for num in n:
        print(f'======{num}个盘子======')
        start_time=time.time()

        cnt=0
        dfs(num,'a','b','c')

        end_time=time.time()
        run_time=round(end_time-start_time,5)

        print(f'运行时间:{run_time}秒, 递归调用次数:{cnt}\n')
        t.append(run_time)
        m.append(cnt)
    end=time.time()
    print("总共运行时间:%s 秒"%(end-start))

    # 创建两幅子图
    fig, (ax1, ax2) = plt.subplots(nrows=2, ncols=1, sharex=True)

    # 在第一幅子图中绘制折线图
    ax1.plot(n, t)
    ax1.set_title("运行时间t随盘子数n的变化")
    ax1.set_ylabel("运行时间t /s")

    # 在第二幅子图中绘制折线图
    ax2.plot(n, m)
    ax2.set_title("递归调用次数m随盘子数n的变化")
    ax2.set_xlabel("盘子数n")
    ax2.set_ylabel("递归调用次数m /次")

    # 调整子图间距
    plt.subplots_adjust(hspace=0.5)

    # 显示图形
    plt.show()

🧡🧡总结🧡🧡

1.让盘子数从2?开始到7进行实验,记录程序运行时间和递归调用次数。
递归调用次数在程序中可以用move()函数调用次数来表示,也即代表移动盘子的次数。
当盘子数从2到7时,由于运行时间都极短(如下图),不方便看出时间上的差距,因此我将盘子数设定为15到22,方便看出关系。
在这里插入图片描述
在这里插入图片描述

2.画出盘子数n和运行时间t?、递归调用次数m的关系图,并进行分析
在这里插入图片描述
可见:随着盘子数的增加,运行时间和递归调用次数也会增加,且都呈指数增长的趋势。其中递归调用次数(移动盘子的次数)为与盘子数的关系为2n-1。同样地,运行时间复杂度为O(2n),随着n次数的增大,求得最终解的时间将恐怖增长。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值