汉诺塔问题

一个n层的汉诺塔,从A移动到C

由于汉诺塔问题本身的限制,我们最先能思考到的点是第n层最后肯定是要放在C的最下面的

有了这个思考后,我们又想,要想使汉诺塔移动次数最小


—— —— —— ——                          ???                                        空         

         A                                                    B                                            C

那么我们就要满足可以A中只剩下n这一张圆盘了,而C中是空的,那么我们就可以直接将A中这一张圆盘直接放入C中

OK,A.C的结构确定了,那B的结构是什么呢?

很显然,由于汉诺塔的特性,所以B中此时是n-1层的汉诺塔

我们再将B中的n-1层汉诺塔移动到C中即可,这个操作完全等同于将n-1层汉诺塔从A中移动至C,且B,C为空这一初始条件

因为B中的n-1层圆盘本身满足汉诺塔结构,且第n-1层是小于C中的第n层的也就是可以将C也看成是空的,所以我们可以乱放,怪放,无限放,终极放,究极皮皮放!

OK,我们还要考虑的是从A中移动n-1层到B,这个问题和从A中移动n-1层到C完全一样!!!

所以抛开第n个圆盘从A移动到C这一个操作外

我们还有从A移动整个n-1层汉诺塔到B,然后从B将整个n-1层汉诺塔移动到C的这两步操作!

OK,无论你叫他递归问题也好,DP问题也好,我觉得更像是递归问题,但我还是写成DP的样子把

DP[n] = 2*DP[n-1]+1

写成递归就好

def hanoi(n):

    if n == 1:

        return 1

    result = 0

    result += hanoi(n-1)

    return result



如果告诉你汉诺塔盘随机地分布在三个柱子上(前提条件是满足每个柱子上依然满足汉诺塔结构),然后问当前状态是不是汉诺塔从A移动到C的必经状态,如果不是返回-1,如果是,返回是当前的第几步

可以这样思考,假设第二个柱子上出现了n号盘子,我们可以肯定的是它不是必经状态因为第n号盘子肯定是直接从A移动到C的

OK有了这个思路就好办了

我们记主柱子为main,辅助柱子为sup,目的柱子为tar

这样记录是有目的的

假设三个汉诺塔是这样的结构

A:main:[X    X]

B:sup:[X    X]

C:tar:[X    X]

假设总共有6号盘子,由上面的结论,从A移动6个盘子到C中总共需要2^6-1 = 63种

我们检查最大的数6在哪个位置

我们知道的是从A将第6号盘子移动到C中是第(63+1)//2   +1  =   32步,

如果6处在sup中,肯定返回-1,

不是的话,我们再看6处在哪个位置

假设6处在tar中,我们可以认为,它可能是将n-1层汉诺塔从sup(B)移动到tar(C)的一个中间过程

那么这个状态就有可能是第34步到第63步中的某一步

记住我们现在的目标是从B中将5层汉诺塔移动到C中,那么此时就与第6个汉诺塔无关

我们将tar中队列最前面的数字弹出tar.pop(0)

且现在的主柱子是B,目标柱子是C,辅助柱子是A,即

A:sup[X    X]

B:main[X    X]

C:tar[X]

同样的,我们看5在哪,如果5在A中,即辅助柱中,肯定没戏,如果在主柱子中,那么肯定在第32到(63-32+1)//2 +1步中

如此循环

因此我们的程序应该是这样的

因为从A移动n个到C中,所以我们记A为主,B为辅,C为目标,且把所有的盘子按1到n进行标号,

将状态放入A.B.C三个列表中

main = [X,X,X,X,X]

sup   = [X,X,X,X,X,X,X]

tar     = [X,X,X,X]

两个指针记录区间

left = 1,right = 2^n-1

当left和right重合时,就是找到的次数

while    left!  !=    right:

        #如果n在辅助队列中直接返回不在必经之路上

        if    n    in    sup:

                return -1

        #如果n在主队列中,将右区间缩减到原区间的终点的左侧

        #且    将目标队列和辅助队列交换位置

        #且    将n从main中弹出

        elif    n    in    main:

                right    =    (left+right)//2-1

                main.pop(0)

                sup,tar    =    tar,sup

         elif    n    in    tar:

                    left    =    (left+right)//2+1

                    tar.pop(0)

                    sup,main    =    main,sup

reuturn left



考虑了一会儿,发现上面一个漏洞

我们的left和right都是指移动了多少步

而最原始的状态应该表示移动了第0步

所以left的初始值应为0

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350