汉诺塔问题及其扩展

news/2026/1/24 17:13:11/文章来源:https://www.cnblogs.com/hicode002/p/19527066

汉诺塔问题及其扩展

:
1个基本模型很多扩展

基本模型:

\(3\)个柱子,\(A,B,C\)\(a\)上有\(n\)个盘子,从上而下从小到大排好,现在要把所有盘子从\(a\)移到\(c\),要求一次只是移动一个盘子,且大的不能在小的上面,求最小的移动次数

这个看起来无从下手,因为最小似乎要枚举所有结果,但是实际上这是一个递归
递归:
把前\(n-1¥个盘子从\)a\(借助\)c\(移到\)b\(,然后把最后一个盘子从\)a\(直接移到\)c\(并输出,再把\)b\(上的\)n-1$个盘子借助a移到c

边界是当只剩下一个盘子时,直接从\(a\)移到\(c\)并输出
其实边界剩下\(0\)个盘子时,也可以直接返回,这样的话还剩\(1\)个盘子的时候\(2\)个递归就结束了,只会输出移动盘子,也可以
至于如何控制递归结束,因为\(n\)个盘子就要移动\(n-1\)个盘子,就要缩小规模,而这样 就可以把还剩下几个盘子作为记录递归进行程度的标志,当只剩下一个或\(0\)个盘子时终止递归

这正确吗?
\(3\)个盘子,
image
把前两个移到\(b\),借助\(c\),就是把\(1\)移到\(c\),再把\(2\)直接移到\(b\),再把\(1\)移到\(b\),接着把\(3\)移到\(c\),然后\(1\)移到\(a\)\(2\)移到\(c\)\(1\)移到\(c\),刚好符合,所以正确 (7次)

公式:
递推:\(f(n)=2f(n−1)+1(n=1−→f(n)=1)\)
\(2^n−1\)

原因:
由于从\(a\)\(b\)借助\(c\)移动\(n-1\)个盘子与从\(b\)\(c\)借助\(a\)移动\(n-1\)个盘子的本质相同,因此\(2f(n-1)\)
然后\(n\)号盘子从\(a\)移到\(c\)需要\(1\)

为什么有
\(2^n−1\)

归纳法:
对于\(f_1\)成立
假设对于\(f_n\)成立,那么证明对\(f_{n+1}\)成立
\(f_{n+1} =2 f_n +1\)
\(=2*(2^n −1)+1\)
\(=2^{(n+1)}−1\)
所以成立

扩展:

盘子编号与剩余盘子个数关系

盘子编号为所有盘子在a柱时自上而下从1到n
在执行递归时,假设当前还剩余x个盘子要从原始柱移到目标柱,那么这x个盘子中编号最大的即最底下的编号是x:
对于n个盘子在a柱时,最底下的编号显然是n,递归时,把前n-1个盘子从a移到b柱,此时这n-1个盘子最底下的是n-1,然后把n号直接从a移到c
接着把n-1个从b移到c,那么此时最底下的还是n-1号盘子,
那么这是什么意思呢?
就是说如何输出具体移动盘子的编号,具体移动时只有两种情况,第一种是只剩下一个盘子,直接移动,第二种是前n-1个已经移到了中间柱,现在要把第n个移动到目标柱,当只剩下一个盘子时,必然是第一个盘子,因为中间那些直接移动都是在递归过程中进行的,没有缩小规模,又因为递归移动的盘子都是前几号盘子,不存在中间插着或移动后几个盘子的情况,所以剩余盘子一定是前几个盘子,因此剩余盘子个数就是前几个盘子的最后一个,而这个盘子参与具体移动,所以输出编号就是输出当前剩余盘子个数(剩余1个时移动的是一号盘子)
这个适用于3柱的不相邻和相邻情况(一下移动n-1个,剩下的不参与递归),不适用于k塔问题(也是一下移动k(n-1)个,且剩下k个不参与递归,只剩下k个时一定是前k个,但是移动时这k个自身顺序会颠倒)
但是4柱或更多不适用(因为4柱第一步r个a移到b,这时最底下编号为r,符合,但是下面n-r个从a移到d是3柱问题,此时最大的编号是n,然而只剩下了n-r个,可以把r+1号作为后面的1号盘)

k塔问题(相同的是否按原顺序排列):

是指三个柱子,kn个盘子,k个盘子一组,它们大小相同,那么从a移到c最小移动步数
首先,方法是递归,先把前k(n-1)个从a借助c移到b,再把最后k个从a移到c,由于大小相同,所以可以直接移动k步,然后再把b的k(n-1)移到c借助a,当n等于1时,直接把盘子从a移到c,需要k

那么
f(n)=2f(n−1)+k(n=1−−−→f=k)
注意k不在递归过程中改变
若k=3
f(2)=9=3∗3
f(3)=21=7∗3

因此猜测f(n)=k∗(2^n −1)
证明:
f(1)=k
假设对于f(n)成立
f(n+1)=2(k(2^n −1))+k
=2^(n+1) ∗k−2k+k
=2^(n+1)∗k −k
=k∗(2^(n+1) −1)
所以成立
从另一个角度分析,每一步都需要k次,但这k次可以直接移动不需要借助盘子,所以就是原来一个盘子一组的步数乘上k,因为可以具体移动时可以直接移动k个盘子,所以并不是f(k*n)(意思是kn个大小不同的盘子a到c的最短步数)

还有一个问题就是如果要求移到c后要求一组内盘子的顺序与原来全在a时这一组内盘子的顺序相同时最少的步数,这个与上面的不一样,因为上面的是直接把k个盘子移动,而这样会把最上面的压到最底下,最底下的改到最上面,但具体不清楚

m柱问题

这是一个拓展问题,指有m个柱子,先从1号柱子移到m号柱子的最少步数
先考虑4个柱子情况:
因为多了一个柱子,所以可以在移动时多借助一个存放,从而减少反复中转(三声)盘子的次数,所以实际上n相同时次数会比3柱的少
那么直接的想法是减少盘子的中转,即递归时取n-2个盘子从1柱移到2柱借助3 4柱
然后n-1盘子移到3柱,n盘子移到4柱,n-1盘子移到4柱,3次,接着把n-2个盘子从2柱移到4柱借助1 3柱
1个盘子时从1直接到4,1次
2个盘子(因为n-2)时1号盘子移到2柱,2号盘子移到4柱,1号盘子再移到4柱,共3次
所以递归为
f(n)=2f(n-2)+3
(f(1)=1 f(2)=3)
但是,当n=6时f(n)=21
可是这并不是最小的,因为当取3个从1柱移到2柱借助3 4柱需要5步,剩下3个从1柱移到4柱只能借助3柱,这是3柱hanoi问题,因此是7步,然后那3个从2柱移到4柱借助1 3柱需要5步,总共5+7+5=17步,这小于21步,
因此,可以发现当我们先从1柱移到2柱盘子个数增大时,可能会增加盘子的中转次数,但是这样剩下的从1柱移到4柱的盘子个数减小,所以这个的移动次数减少,需要达到一个平衡,而这个平衡点就是最小移动次数,就像二次函数一样
那么该怎么做呢?
很简单,既然我们无法确定从1柱移到2柱多少个盘子,那么就枚举,找到一个移动数r使得当前的n的总移动次数最小就是了。
这里有一点贪心,就是说f n里的r的值能使总和最小,且f r里可能有不同的r的值,但是f r也是最小的,那么所求的就是总体的最小值(即这个r的取值下f r是最小值,而总和也是最小值)

现在设计算法:
先移动r个盘子从1柱到2柱借助3 4柱
然后将剩下的n-r个盘子借助3柱从1移到4柱(2柱被占了)
接着把2柱的r个盘子从2柱移到4柱借助1 3柱(第二步后1柱空了,3柱也空了)
r通过枚举找到一个r,使得当前的n的总移动次数最小
r的取值范围,r为0时一个盘子也不移动,只是把n个盘子借助3柱移到4柱,那浪费一个柱子,次数肯定不是最优,不用算,r=n的时候,一下把n个从1柱移到2柱,然后剩下0个移到4柱,再直接从2柱把n个移到4柱,这绕了一圈,肯定不是最优,不用算,所以0<r<n
那么问题就简单了
递推公式
f(n)=2f(r)+2^(n−r) −1
(0<r<n,且r值能使f(n)最小)
边界:
n=1时,一个盘子,只需要1次
n=2时,两个盘子,像3柱一样,3次

具体发现有很多重复,因为会反复计算,因为每次枚举r时总有些重复,因此可以考虑记忆化或递推
那么递推是反着来的,先算f(1) f(2)
然后f(3)开始,枚举r,然后找f(r),因为0<r<n
所以当前的r一定在前面算过,然后找出最小值,更新这次的f(n)即可,一直算到n

由此可以推广到m柱问题
同样,无法确定一次移动多少个盘子,我们希望盘子中转次数少,所以一次我们移动后剩下的最好刚好摊开在后面,即从1柱 移到2柱时,最好移动n-(m-2)个,剩下m-2个从1柱借助m-3个柱子移到4柱,即这m-3个柱子每个刚好摊开一个盘子,然后第m号柱子放最大的盘子,然后把m-1号移到m,m-2号移到m,。。。。。。共m-3次,而摊开需要m-2次,共2m-5次
然后再把n-(m-2)个从2柱移到m柱借助m-2个柱子
但是,根据4柱的经验,我们知道这并不是最优,因为虽然减少了盘子中转的次数,但是却增大了从1移到2柱和从2柱移到m柱的递归的次数
所以还是要枚举r找平衡

所以frame算法如下:
首先先将r个盘子从1柱移到2柱,借助m-2个柱子
然后将剩下n-r个盘子从1柱移到m柱,借助m-3个柱子
接着把2柱的r个盘子从2柱移到m柱,借助m-2个柱子
其中0<r<n
理由同4柱
r的取值是使当前n的移动次数最小的r的取值
递推公式
f(n,m)=2f(r,m)+f(n-r,m-1)
其中0<r<n
且r能使得当前的函数取值最小
然后边界:
n<=0 0次
n>0&&m==1 0次
n=1 m>1 1次

这可以做递推

先算m=1的,全改成0
再算n=1 m>1的,全改成1
然后其他的都是0
然后,外层循环是2~m,内循环从2到n,倒过来也行,然后枚举r从1到n-1,找出函数最小值并更新

只能相邻柱子移动

就是a到b可以,b到c可以,a到c不可以,求最短步数
那么这样就可以设计一个新算法:
把a柱前n-1个借助b移到c柱
第n个从a移到b
c柱前n-1个从c移到a柱借助b柱
第n个从b移到c
a柱前n-1个移到c借助b柱

理由:
相邻柱子不易直接设计递归,所以用了看似错误的递归
实际上是先把a柱的借助b移到c柱,这是要过中转柱的,没有错误
然后第n个直接移动
……
都是一样的,算法可行

递推公式
f(n)=f(n-1)+1+f(n-1)+1+f(n-1)
=3f(n-1)+2
边界:
f(1)=2
1个盘子a到c最少过b,两次
因为是n-1,所以是连续缩减规模的,只考虑1即可
通项公式:
f(n)=3^n−1
证明:
归纳法:
首先f(1)显然成立
假设对f n成立
那么证明f(n+1)成立
f(n+1)=3f(n)+2
=3*(3^n−1)+2
=3^(n+1)−3+2
=3^(n+1)−1
所以成立

只能相邻柱子移动且最大的盘子可以在最上面(只有n个中最大的可以,递归时最大的不可以)

原来我们很麻烦的移,但现在简单了
只需要把前n-1个移到b,然后第n个移到b再移到c,最后b向c移动那n-1个
也就是说需要求从其他柱向中间柱移动的递归
注意不是f(n)=2f(n-1)+2
因为n-1 n-2 号都不能直接放在最上面
实际上可以分类递归
g(n)是从边缘柱到中间柱的最小次数
s(n)是从边缘住到另一个边缘柱的最小次数
s(n)=3s(n-1)+2
s(1)=2
所以s(n)=3^n -1
那么g(n)呢?
设从a向b柱移动
前n-1个由a移到c
第n个a->b
然后n-1个c->b
所以g(n)=s(n-1)+1+g(n-1)
g(1)=1
所以
g(n)=3^n-1 + g(n-1)
g(n)=3^n-1 + 3^n-2 +…..+1
可见是等比数列的和
g(n)=1*(1-3^n)/-2 =(3^n -1)/2
那么最后移动次数为
2g(n-1)+2 =3^(n-1) -1+2=3^(n−1)+1

编号k的盘子移动次数

3柱普通hanoi问题中,求编号为k的盘子实际移动的次数
f(n)=2f(n-1)+1
也就是说n需要1次
而n-1需要2次

n-2需要4次
也就是说编号为k的盘子的移动次数等于f(k)的调用次数,因为f(k)里有一次对k的直接移动
而f(k)只由f(k+1)调用而来,因此f(k)的调用次数只与比它大的编号的调用有关,与比它小的盘子无关
f(k)自身调用1次 =2^0
f(k+1) 2=2^1
f(k+2) 4=2^2
.
.
.
f(k+n-k)=f(n) 2^(n−k)
因此编号为k的盘子移动次数为 2^(n−k)
3柱只能相邻柱移动的hanoi中,求编号为k的盘子的移动次数
f(n)=3f(n-1)+2
因为这里k的直接移动在f(k)中有2次,1次是a->b,1次是b->c
而编号为k的盘子的移动次数等于f(k)的调用次数*2
f(k)由比k大的调用,与小的无关
f(k) 1=3^0
f(k+1) 3=3^1
f(k+2) 9=3^2
f(k+n-k)=f(n) 3^(n−k)
所以编号为k的盘子的移动次数等于2∗3^(n−k)

拓展到m柱问题
没有通项公式
但可以倒推+分治
f(n,m)=2f(r,m)+f(n-r,m-1)
这样先算出r,然后看一看k<=r吗
若是,移动次数就是r,m下k的移动次数*2
否则,让k-=r
然后继续递归
当m=3时,直接输出2^(n-k)

符合大的在小的下面的全部的盘子摆放情况(种类数)

排列组合问题
既然是大的在小的下面,那么就应该先考虑大的,这样便于确定小的
如果反过来就不对了
先考虑3个时
第n个可以在1 2 3柱上的一个
3种
然后第n-1个可以在1 2 3柱中的1个
3种
……
以此类推,到第一个还可以在1 2 3柱中的一个
状态是叠加的
所以最后是3^n
没有顺序问题
最大的就3种,而比它小一点的必须在它的紧上面,不能再往上,再往上的话就不符合大的在小的下面了
m柱时
是m^n
因为第n个可以选m种,第n-1个可以选m种……

4柱hanoi通项公式

可以确定r的取值
r=floor((√(8n+1)−1)/2)
记忆公式,n=6时,8n+1=49
sqrt后为7,7-1=6,6/2=3
刚好
那么这样的话就可以递归时不枚举r,而是直接代进去递归,提升了效率
还有O(1)公式
f(n)=(n−(r2−r+2)/2)∗2r+1
当n=6时,r=3
3^2=9 9-3=6 6+2=8 8/2=4 6-4=2 2*8+1=17

现在的情况到目标状态的最少步数

判断是否是最优解过程中的一个状态(给定状态):

递归判断,首先第n个盘子要么在a要么在c,但是永远不可能在b,
因此可以设计递归,参数是当前要检查的盘子编号,起始柱子a,中间柱b,目标柱c
那么我们可以检查当前这个第n号盘子是否在a或c盘,若在b盘则不符合,若在a,则说明这些盘子正在进行a到b盘的操作,那么我们可以缩减规模判断n-1号盘子在a还是b盘,若在c,则不符合,如此递归
而第n号如果在c,说明将要或正在进行b到c,那么可以递归判断n-1号是否在b或c上
当只剩下一个盘子时,只需要检查1号盘子是否在a或c上,若是,则符合,若在b上,则不符合
极端考虑:
当所有盘子都在a时,满足递归吗?
因为是a,b,c->a,c,b->a,b,c……
第n号在a,第n-1号在a,第n-2号在a……第1号在a
所以满足递归
当所有盘子在c时:
a,b,c->b,a,c->a,b,c……
所以满足递归

所以递归正确
这是个倒推,原来是求每种状态,现在通过分治性质的算法用n的复杂度倒推出来是否最优

安排优先级的hanoi

3个盘子3个柱,已知两个盘子所在的柱(不同柱),快速求另一个盘子所在的柱

柱子编号为1 2 3
若2个盘子所在柱子编号已知且所在柱子不相同,那么第三个盘子所在柱子为前两个所在柱子编号相互异或后的结果
若 1 3
01
11
10--->2

若1 2
01
10
11--->3
若2 3
10
11
01--->1

求第k次移动的盘子编号和起始终止柱

倒推的分治算法
f(n)=2f(n-1)+1
f(n)=2^n−1
因此f(n-1)=2^(n−1)−1
中间那一次是第2^(n−1)

然后判断k若等于2^(n-1)
那么输出n和起始终止柱
如果k小于的话,就继续递归
若k大于的话,就让k=k−2^(n−1)
然后继续递归

非递归解法

m柱hanoi的通项公式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1210633.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

揭秘天猫超市购物卡回收其中的猫腻

如今,很多人手中都有闲置的天猫超市购物卡,想通过天猫超市购物卡回收变现来盘活资源,可回收过程中猫腻不少,一不留神就可能遭受损失。一、回收猫腻大起底1、二手平台风险重重行业数据显示,二手平台上购物卡回收纠…

三分之一2-5天和三分之二6-13天资金利用率对比学习

目录一、基础参数定义&#xff08;统一口径&#xff09;1. 基础仓位金额计算二、资金周转率与时间周期的数学建模1. 周期天数区间与均值2. 资金周转率定义&#xff08;单次交易&#xff09;3. 周转率差值与比例&#xff08;1&#xff09;周转率差值&#xff08;2&#xff09;周…

Spring Cloud Alibaba 2025.0.0 整合 ELK 实现日志 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Android关机

adb shell reboot -p

221_尚硅谷_实现接口和继承比较(2)

221_尚硅谷_实现接口和继承比较(2)1.实现接口可以当作是对继承的一种补充 2.实现接口和继承

2026年苏州智能硬件设计公司推荐:飓风工业设计,企业产品设计/专业工业设计/产品外观设计/电子产品设计/工业设计/机械产品设计公司精选

在数字化转型浪潮中,优秀的工业设计公司正凭借数据驱动和技术融合,重新定义产品竞争力。 工业设计正经历从传统外观造型设计向技术集成运用的现代工业设计转变。 市场报告显示,全球工业设计服务市场规模持续增长,智…

2026年国内知名的投影机品牌排名,激光投影仪/20000流明投影机出租/画展投影机出租/雾幕投影机,投影机公司排行

评测背景:聚焦服务与保障,重新定义“强”的标准 随着展览展示、文旅演艺及高端会议市场的蓬勃发展,专业投影设备的需求已从单一的产品性能,扩展至包含方案设计、设备保障、现场执行与全国化服务在内的综合能力比拼…

JAVA自学之路1.1:JAVA入门纠错

1.1、JAVA入门纠错 在JAVA入门这篇文章里有些问题和错误需要纠正,懒得再改那篇文章了,直接写在这好了。 package test.test1;public class HelloWorld {public static void main(String[] args) {System.out.println…

2026软考高级系统架构师备考资料-录播+直播

【手机复制括号内整段内容&#xff0c;打开「夸克APP」即可获取。 伏脂燹烜煘胁氟洞座 /~e9ef3ABPYp~:/】

微信立减金回收攻略,方法、流程与折扣全解析

在移动支付广泛普及的当下,微信立减金成了消费者常用的优惠凭证。但受消费场景限制或有效期临近影响,大量立减金闲置浪费。如何通过正规渠道快速变现?本文将从方法、流程、折扣三方面,结合权威数据与行业实践给出答…

安达发|精准排产,守护生命:医疗器械行业车间排产的数字化革命

在关乎人类生命健康的医疗器械制造领域&#xff0c;每一台设备、每一个部件的准时交付&#xff0c;都可能直接影响到患者的治疗与康复。这个行业以其严苛的质量法规&#xff08;如FDA、ISO 13485&#xff09;、复杂的生产工艺和极高的可追溯性要求而著称。在这样的背景下&#…

2026年市场评价好的纸盒品牌推荐排行,纸盒/彩印包装/农产品纸箱/工业纸盒/纸箱/工业纸箱,纸盒批发厂家推荐排行

在工业生产与商品流通领域,纸盒作为产品包装的核心载体,直接影响着商品运输安全、市场展示效果及品牌价值传递。随着国内制造业、电商物流、食品加工等行业的快速发展,纸盒需求量持续攀升,但市场产品质量参差不齐,…

Deepseek问答:开发人员如何选书

如果觉得好&#xff0c;请点赞、收藏、转发和关注&#xff0c;感谢您&#xff01;仅供参考问&#xff1a;按照开发人员的用途、职位、技能掌握程度、预算、可支配时间五个方面提出选择编程书籍的技巧ds答&#xff1a;为不同背景和需求的开发人员选择编程书籍是一项需要精细匹配…

php开源短视频源码,JSON对象转化API

php开源短视频源码&#xff0c;JSON对象转化API 1. 入门案例 package com.jt.pojo;import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArg…

短视频平台php源码,字符缓冲流的特有功能

短视频平台php源码&#xff0c;字符缓冲流的特有功能 一、字符缓冲流的特有功能 void newLine() 换行操作&#xff1a; 三个步骤: write;newLine;flush; 当然最后close; public String readLine() 读一行,只读内容&#xff0c;不读换行的符号&#xff01;操作&#xff1a…

短视频app搭建,如何实现毛玻璃效果?

短视频app搭建&#xff0c;如何实现毛玻璃效果&#xff1f; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"vi…

小视频平台源码,ElementUI 本地分页

小视频平台源码&#xff0c;ElementUI 本地分页 因为一些业务需求,需要用到前端本地分页,直接上代码 <el-table :data"orderList.slice((pageNo-1)*pageSize,pageNo*pageSize)" empty-text"暂无数据" v-loading"orderLoading"> </el-t…

C 语言基础:输入输出、运算符与流程控制全梳理

好的&#xff0c;我们来一次C语言基础的系统梳理&#xff0c;重点覆盖你提到的三大块&#xff1a;输入输出、运算符、流程控制。 这份内容适合零基础或想快速复习的人&#xff0c;全部用最实用、最常考的写法和注意点&#xff0c;强烈建议你边看边敲代码验证。 一、C程序基本结…

鸿蒙APP开发从入门到精通:ArkUI组件库详解与常用组件实战

鸿蒙APP开发从入门到精通&#xff1a;ArkUI组件库详解与常用组件实战 鸿蒙&#xff08;HarmonyOS NEXT&#xff09;是华为推出的分布式操作系统&#xff0c;其APP开发框架以ArkUI为核心&#xff0c;采用ArkTS&#xff08;基于TypeScript的扩展语言&#xff09;进行声明式开发。…

Typescript——泛型

一、问题的引入 需求&#xff1a;创建一个函数&#xff0c;我想要传入啥参数&#xff0c;就返回啥&#xff0c;传入的参数和返回的值的类型相同&#xff0c;那么针对这个需求&#xff0c;我们应该如何去做&#xff0c;大家很快就会想到下面的这种办法。 function hhh(value: …