【基本算法题-2022.7.30】9. 奇怪的汉诺塔

每日一题包含七大板块,现在从最基本的算法题开始,此类题型包括位运算、递推、递归、二分、排序、贪心等,从简单到复杂,跟我一起从点滴积累,到最终一举成名,打遍天下!✨


💻基本算法题9. 奇怪的汉诺塔

汉诺塔问题,条件如下:

1、这里有 A、B、C 和 D 四座塔。

2、这里有 n 个圆盘,n 的数量是恒定的。

3、每个圆盘的尺寸都不相同。

4、所有的圆盘在开始时都堆叠在塔 A 上,且圆盘尺寸从塔顶到塔底逐渐增大。

5、我们需要将所有的圆盘都从塔 A 转移到塔 D 上。

6、每次可以移动一个圆盘,当塔为空塔或者塔顶圆盘尺寸大于被移动圆盘时,可将圆盘移至这座塔上。

请你求出将所有圆盘从塔 A 移动到塔 D,所需的最小移动次数是多少。
汉诺塔塔参考模型
输入格式
没有输入

输出格式
对于每一个整数 n,输出一个满足条件的最小移动次数,每个结果占一行。

数据范围
1≤n≤12

输入样例:

没有输入

输出样例:

参考输出格式

🍀题解 — DP+递推

对于汉诺塔问题,我们究其根底

约定:

  1. 我们用ABCDE来命名塔的名字,
  2. 默认初始的圆盘都在A塔上,最终要移动到最后一个塔上。
  3. d 数组存放3个塔的结果,f 数组存放4个塔的结果, g 数组存放5个塔的结果

两个塔(AB)

如果只有两个塔,那么只有圆盘个数为一时,答案为1,其余答案为0

三个塔(ABC)

如果有三个塔,移动时我们需要借助二塔里的结论

如果要移动 n 个圆盘,我们需要在三塔的情况下,将上面 n - 1 个较小圆盘移动到B塔,在将一个大圆盘移动到C塔,最后在将 n - 1 个圆盘在三塔的情况下从B移动到C塔

结论:d(n) = d(n - 1) + 1 + d(n - 1)

四个塔(ABCD)
解决完三塔问题,四塔问题将于三塔类似

如果要移动n个圆盘从A到D的话,我们的解决方法是将一部分圆盘(i个圆盘)先移动到B(或者C),因为这前几个圆盘都是非常小的,后面剩下的大圆盘不能压在上面,所以放小圆盘这个塔暂时不能使用

那么问题将会变成,怎么在三塔情况下将n - i 个圆盘从A移动到D,这时可以用三塔的结论;

问题1:我们先移动的一部分圆盘到底是几个呢,我们需要枚举,最终答案取最小值。

结论:先把前 i 个盘子在四塔情况下移动到B,剩下的盘子在三塔情况下移动到D,最后在将那 i 个小的盘子在四塔情况下从B移动到D。

f(n) = min(f(n), f(i) + d(n - i) + f(i)) 0 <= i <= n;

对于这道题:

首先,可以初步确定,这是一道递归/递推的题目。

我们先考虑三个塔的汉诺塔问题,最优秀方案:必然是先挪走n-1个圆盘,然后再挪走圆盘N,

因此可以得出递推方程也就是 d[i]=d[i-1]*2+1;

之所以要乘以2,是因为第一次挪到第二个塔,然后还要挪移回到第三个塔,下面四个塔也是这样的

接着考虑四塔问题,我们可以这么思考,首先挪走j个塔,也就是有四个塔可以选择,然后再挪走剩下的n-j个塔,此时有三个塔可以选择,因此这就是我们的状态转移方程:

f[i]=min(f[i],f[j]*2+d[n-j]);其中i表示当前一共有几个塔,也就是上文所说的n

📝代码展示

#include <bits/stdc++.h>
using namespace std;
int d[21],f[21],i,j;
int main()
{
    for (i=1;i<=12;i++)
        d[i]=2*d[i-1]+1;
    memset(f,0x3f,sizeof(f));
    f[0]=0;
    for (i=1;i<=12;i++)
        for (j=0;j<i;j++)
            f[i]=min(f[i],f[j]+f[j]+d[i-j]);
    for (i=1;i<=12;i++)
        cout<<f[i]<<endl;
}


在这里插入图片描述

【🎯知识点:递推算法】

递推 是指将一个看似复杂,难以求解的问题一步步的转换成小问题,最后到达一个(或若干个)基本解,这些基本解很好想出来,也有的是人为规定的,然后再依赖这些基本解一步一步反向求解最初的大问题的过程。

举一个最简单和常见的例子,斐波那契数列,这个数列的每一项等于前面两项之和。如下:

{1,1,2,3,5,8,13…}

如果让你直接求斐波那契数列的第100个数f(100),很难直接想出来,但是我们可以通过找到如下的递推关系:f(n)=f(n−1)+f(n−2),并且确定基本解f(1)=1f(2)=1(因为递推关系只依赖前面两项,所以只求出基本的两项即可),之后就可以求出f(3),再用f(2)+f(3)求f(4),最后求解到f(100)。

很多问题可以找到递推关系,所以这个工具很常用,比如解决具有重叠子问题的递推关系的算法叫“动态规划”,它出现在很多面试题和算法竞赛当中 。


持续更新,喜欢的话欢迎点赞👍、收藏⭐️+关注✌️哟~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值