用问题归约法思想解决梵塔问题(python递归实现)

梵塔规则

        有a、b、c三个柱子,a从上到下,从小到大有n个盘子。要求把a上所有盘子移动到c,一次只能移动一个盘子,且大盘子不能放小盘子上

分析梵塔解决过程

        (1)将最上面的n-1个圆盘从a移动到b
        (2)将初始位的最底下的一个圆盘移动到c
        (3)将b的n-1个圆盘移动到c

例如

        

当移动两个盘子的时候,得需要三步才能完成。例如:把a上的两个盘子移动到c

    第一步:先把a上的1个移动到b
    第一步:再把a上最后1个移动到c
    第一步:再把b上仅有的一个移动到c

当移动三个盘子的时候,就可以分解成先移动两个盘子(可以看成当移动2个盘子时),再移动一个盘子,再将两个盘子移动(3步)


当移动四个盘子的时候,就可以分解为先移动三个盘子(又可以看成当移动3个盘子时),再移动一个盘子。再移动三个盘子(3步)

所以当移动两个或者两个以上的盘子时,可以用归约法将问题依次分解,每次分解都是3步,分解直至当移动两个盘子,而移动2个盘子也需要3步,因此这就是一个递归的问题,同样的,用递归实现即可

代码

# n:层数,a:初始柱,b:过度柱,c:目标柱
def move(n,a,b,c):
    
    # 如果层数为1,可以直接到目标柱
    if n==1:
        print(a,"-->",c)
        
    # n-1:分解
    else:
        move(n-1,a,c,b)   # 第一步
        move(1,a,b,c)  # 第二步
        move(n-1,b,a,c)  # 第三步
        
if __name__=="__main__":
    
    n=int(input("请输入层数:"))
    move(n,"A","B","C")
    

效果图:

动画效果代码

import turtle

class Stack:
    def __init__(self):
        self.items = []
    def isEmpty(self):
        return len(self.items) == 0
    def push(self, item):
        self.items.append(item)
    def pop(self):
        return self.items.pop()
    def peek(self):
        if not self.isEmpty():
            return self.items[len(self.items) - 1]
    def size(self):
        return len(self.items)

def drawpole_3():               #画出汉诺塔的poles
    t = turtle.Turtle()
    t.hideturtle()
    def drawpole_1(k):
        t.up()
        t.pensize(10)
        t.speed(100)
        t.goto(400*(k-1), 100)
        t.down()
        t.goto(400*(k-1), -100)
        t.goto(400*(k-1)-20, -100)
        t.goto(400*(k-1)+20, -100)
    drawpole_1(0)               #画出汉诺塔的poles[0]
    drawpole_1(1)               #画出汉诺塔的poles[1]
    drawpole_1(2)               #画出汉诺塔的poles[2]

def creat_plates(n):            #制造n个盘子
    plates=[turtle.Turtle() for i in range(n)]
    for i in range(n):
        plates[i].up()
        plates[i].hideturtle()
        plates[i].shape("square")
        plates[i].shapesize(1,8-i)
        plates[i].goto(-400,-90+20*i)
        plates[i].showturtle()
    return plates

def pole_stack():                #制造poles的栈
    poles=[Stack() for i in range(3)]
    return poles

def moveDisk(plates,poles,fp,tp):#把poles[fp]顶端的盘子plates[mov]从poles[fp]移到poles[tp]
    mov=poles[fp].peek()
    plates[mov].goto((fp-1)*400,150)
    plates[mov].goto((tp-1)*400,150)
    l=poles[tp].size()           #确定移动到底部的高度(恰好放在原来最上面的盘子上面)
    plates[mov].goto((tp-1)*400,-90+20*l)

def moveTower(plates,poles,height,fromPole, toPole, withPole):#递归放盘子
    if height >= 1:
        moveTower(plates,poles,height-1,fromPole,withPole,toPole)
        moveDisk(plates,poles,fromPole,toPole)
        poles[toPole].push(poles[fromPole].pop())
        moveTower(plates,poles,height-1,withPole,toPole,fromPole)

myscreen=turtle.Screen()
drawpole_3()
n=int(input("请输入汉诺塔的层数并回车:\n"))
plates=creat_plates(n)
poles=pole_stack()
for i in range(n):
    poles[0].push(i)
moveTower(plates,poles,n,0,2,1)
myscreen.exitonclick()

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值