递归问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_26564783/article/details/77719432

递归

所谓递归实际是函数嵌套调用本身的过程,同时程序在调用函数过程实质是不断入栈和出栈的过程。有关递归的问题就其数据流是类似于栈操作数据先进后出的性质,简言之,就是在解决一些问题的时候需要解决更深入一个层次去解决内在的问题同时需要保留当前状态,等到内部问题解决了返回原来的位置再接着执行。

举个简单的例子:求1+2+3……+100=?

那么,要求这个式子的总和可以求出1+2……+99的值,然后加上100即可。问题便转化为求内部一个问题(1+2……+99 = ?)和100的和这样一个问题。接下来可以不断去深化问题直到最后内部是求1=?,显然1=1,这时这个内部问题终于得到解决,此时便可以依次回溯直至求出最终答案。

    def sum( n):
        if n == 1:
            return 1
        else:
            return sum(n - 1) + n

if __name__ == '__main__':
    print sum(100)

汉诺塔问题 

这里有关递归的经典问题即汉诺塔问题,记得在学C语言的时候,一开始接触递归的概念就是在解决汉诺塔问题时候。简言之,问题即如何把一堆从小到大叠好的盘子(小的在上,大的在下)从原来位置移到另一堆,规则是一次只能移动一个盘子,且始终保持所有盘子小的在上大的在下。(盗用一张网上的图)

 
 

  

问题并不复杂,可以循序渐进扩大数据集考虑这个问题:

一个盘子情况:

扫描二维码关注公众号,回复: 3004420 查看本文章

第1 次移动 :  把 1 号圆盘从 A->C

两个盘子情况:

第1 次移动 :  把 1 号圆盘从 A->B    

第2 次移动 :  把 2 号圆盘从 A->C    

第3 次移动 :  把 1 号圆盘从 B->C

三个盘子情况:

第1 次移动 :  把 1 号圆盘从 A->C   

 第2 次移动 :  把 2 号圆盘从 A->B    

第3 次移动 :  把 1 号圆盘从 C->B  

 第4 次移动 :  把 3 号圆盘从 A->C   

第5 次移动 :  把 1 号圆盘从 B->A   

第6 次移动 :  把 2 号圆盘从 B->C   

第7 次移动 :  把 1 号圆盘从 A->C

实际就两个盘子情况作为参考,要将一堆盘子按规则移动到C,那么势必最大的盘子放到C过后,其余的盘子才能想办法往上堆。问题可以简化为要将n个A堆的盘子移动到C,可以进行如下几步:

(1)将n-1个盘子借助C移动到B。

(2)最大的那个盘子直接从A移动到C。

(3)n-1个盘子借助A移动到C。

            

接下来,当在解决n-1个盘子的移动问题自然就会再次使用这样的模式来移动,如此形成了递归调用。

汉诺塔问题+(杭电acm 汉诺塔III)

在杭电acm上还看到一个改造版的汉诺塔问题,不过,无论怎么变化,只要理解问题的实质,求解就并非难事。(http://acm.hdu.edu.cn/showproblem.php?pid=2064)现在的问题是这样的:现在我们改变游戏的玩法,不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到下盘的上面。同样在可以借助前面的思考方式:

一个盘子的情况:

第1 次移动 :  把 1 号圆盘从 A->B

第2 次移动 :  把 1 号圆盘从 B->C

两个盘子的情况

第1 次移动 :  把 1 号圆盘从 A->B   

第2 次移动 :  把 1 号圆盘从 B->C   

第3 次移动 :  把 2 号圆盘从 A->B   

第4 次移动 :  把 1 号圆盘从 C->B  

 第5 次移动 :  把 1 号圆盘从 B->A   

第6 次移动 :  把 2 号圆盘从 B->C   

第7 次移动 :  把 1 号圆盘从 A->B   

第8 次移动 :  把 1 号圆盘从 B->C

实际,问题其实就是这样的,一个盘子则将其 从A->B->C,两个或多个的时候,则:

(1)首先将n-1个盘子从A->B->C。

(2)再把最大的盘子从A->B。

(3)n-1个盘子从C->B->A。

(4)将最大的盘子从B->C。

(5)最后将n-1个盘子从A->B->C。

如此问题最终得到解决。最后将两个汉诺塔的问题代码附上:

class Hanuo(object):
    count = 0

    def move(self, disk, start, end):
        self.count += 1
        print "第" + str(self.count) + " 次移动 : " + " 把 " + str(disk) + " 号圆盘从 " + start + "->" + end

    def Hanuota(self, n, a, b, c):
        if n == 1:
            self.move(n, a, c)
        else:
            self.Hanuota(n - 1, a, c, b)
            self.move(n, a, c)
            self.Hanuota(n - 1, b, a, c)

    def Hanuota2(self, n, a, b, c):
        if n == 1:
            self.move(n, a, b)
            self.move(n, b, c)
        else:
            self.Hanuota2(n - 1, a, b, c)
            self.move(n, a, b)
            self.Hanuota2(n - 1, c, b, a)
            self.move(n, b, c)
            self.Hanuota2(n - 1, a, b, c)

if __name__ == '__main__':
    han = Hanuo()
    han.Hanuota2(2, 'A', 'B', 'C')
 
 
 

猜你喜欢

转载自blog.csdn.net/qq_26564783/article/details/77719432
今日推荐