奇怪的汉诺塔,四个塔

题目

首先我们来看一下题目 

汉诺塔问题,条件如下:

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

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

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

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

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

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

请你求出将所有圆盘从塔A移动到塔D,所需的最小移动次数是多少。

输入格式:

任意多行,每行包含一个整数n。1≤n≤12

输出格式:

对每一行输入,在对应一行中输出一个满足条件的最小移动次数的值。

输入样例:

1
3

输出样例:

1
5

分析

我们之前探讨过正常的汉诺塔问题(三个),详细看我的第一篇博客。

http://t.csdnimg.cn/ZKND5

三个汉诺塔时用到了函数的递归方法

对于n个圆盘,将它们从塔A动到塔C,可以分解为以下步骤:

  1. 将n-1个圆盘从塔A移动到塔B;
  2. 将第n个最大的圆盘从塔A动到塔C;
  3. 将n-1个圆盘从塔B移动到塔。

而四阶的会比三阶的更加复杂,因为多了更多的选项

还是让我们从少的开始慢慢向后推进

当只有一个时候,明显是1

当只有两个时候,明显是3    前两个的值和三阶汉诺塔是相同的

但是到三个时候,变成了5   而三阶汉诺塔是7 ,从这开始出现差别

当到第四个时候,我又想起了类似于三阶汉诺塔的方法,将一部分看成一个整体去进行计算,将第一个和第二个看成一个整体去进行移动,

所以此时就是 (假设令求汉诺塔次数的函数为f4()),2*f4(2) +3;

所以就产生递归为f(x) = 2*f4(2) + 3     但是此时得出的结果是

但是实际的结果是

 

发现从第六个开始就不正确,并且看不出来从 6之后有任何的规律

这是为什么呢,因为上述的计算其实是f4(x-2) + f3(2)(f3()为三阶汉诺塔的移动次数)

其实可以看出,四阶汉诺塔可以看成

层数较少的四阶汉诺塔和三阶汉诺塔的组合

什么意思呢

举个六层的例子

假设先将上面三层看成一个整体,进行移动到B/C柱,然后将剩余的三个大的移动到D上,又因为上面三个占住了一个柱子,所以移动剩余三个柱子就变成了三阶汉诺塔的问题,最后再将上方是哪个移动到D上

所以依次类推四阶汉诺塔步骤为

1.首先 将n-k个盘子移动到B或C柱
2. 然后将k个盘子移动到D柱(这个步骤是三汉诺塔问题)
3. 最后将最开始移动的n-k个盘子移动到D柱

所以就是 f4(x) = 2 * f4(n - k) + f3(k)   又因为要求最小值,所以就要进行比较,k取何值时取得最少的步骤。

所以总体思路已经明确了,下面进行代码实现

 代码实现

#include <stdio.h>  

int main()
{
    int f4[100] = { 0 };//用来存放三阶汉诺塔的移动次数
    int f3[100] = { 0 };//用来存放三阶汉诺塔的移动次数
    f3[1] = 1;
    int num = 0;
    scanf("%d", &num);
    //计算三阶汉诺塔
    for (int i = 2; i <= num; i++)
    {
        f3[i] = 2 * f3[i - 1] + 1;
    }
    //计算四阶汉诺塔
    memset(f4, 0x3f, sizeof(f4));//将其中的值变成很大的数,方便后续进行最小值的比较
    f4[0] = 0;
    for (int n = 1; n <= num; n++)
    {
        for (int k = 0; k <= n; k++)
        {
            f4[n] = (f4[n] < (2 * f4[n - k] + f3[k])) ? f4[n] : (2 * f4[n - k] + f3[k]);
        }
    }
    printf("%d", f4[num]);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值