汉诺塔的动态规划

本文通过汉诺塔问题探讨动态规划,介绍了汉诺塔的动态规划解法,包括汉诺塔II、III和IV的变种问题,强调了理解和找到状态转移方程的重要性。并提供了各变种问题的最少移动次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

还记得刚入大学的时候,当时也不会什么算法现在也啥也不知道 ,老师在讲递归的时候布置了汉诺塔这道题,因为当时是纯粹的在教C语言的语法,所以当时做这道题的方法就是纯粹的模拟暴力永远滴神。纯粹的模拟也有非常大的问题,不急耗时长,还占内存。当时也因为不太熟悉语法,卡过很长一段时间来着本蒟蒻实在是太菜了啊…在这里插入图片描述

经过暑假的学习后,也学到了一些算法的皮毛,在了解到汉诺塔的操作规律之后,也让我对动态规划的理解更深刻一些了,动态规划的解题的关键点在于找到状态和找出状态转移方程,也就是了解题目到底是在干什么,它符合哪些数学规律。

汉诺塔小游戏传送地址
在这里插入图片描述
汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。
对于汉诺塔这一类型的题目来说其实就是属于“把大象装进冰箱要几步的问题”:我们都知道只要三步,第一步,打开冰箱门;第二步,把大象放进冰箱;第三步,关上冰箱门。对于汉诺塔来说:最底下的大盘就是“大象”,而把“大象”上面的圆盘整块移走就是“打开冰箱门”;大圆盘放到目标位置就是“把大象放到冰箱”;“关上冰箱门就是”把其他圆盘按照规律的放到“大象”上,而这个步骤又可以看成下一个“把大象放进冰箱要几步的问题”(这个结果大家也明白没啥区别),形成了一个“套娃”。禁止套娃!!!在这里插入图片描述
设三柱为A(初始柱)、B(中间柱)、C(目标柱)柱,把“大象”送进冰箱,需要先把其他圆盘移到另一个柱子上,移开最顶上的圆盘只要1次,移开两个圆盘就需要3次(把第一个圆盘移到B柱一次,把第二个圆盘移到C柱,再将一号盘移到二号盘上面——C柱),移开三个圆盘需要7次(重复上一个步骤把一、二号移到B柱-3步,把三号盘移到C柱-1步,把一、二号盘移到C盘上-3步)…由此可见,设汉诺塔移动步数为F(n),则F(n)=2F(n-1)+1,显而易见F(1)=1;所以F(n)=2^n-1就是汉诺塔的递推式。(单纯的找规律得递推式也很快)
接下来几道汉诺塔的变种题我就不解释了,做法是一样的在这里插入图片描述

汉诺塔II HDU - 1207

原题传送
Problem Description

经典的汉诺塔问题经常作为一个递归的经典例题存在。可能有人并不知道汉诺塔问题的典故。汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。也有人相信婆罗门至今仍在一刻不停地搬动着圆盘。恩,当然这个传说并不可信,如今汉诺塔更多的是作为一个玩具存在。Gardon就收到了一个汉诺塔玩具作为生日礼物。
Gardon是个怕麻烦的人(恩,就是爱偷懒的人),很显然将64个圆盘逐一搬动直到所有的盘子都到达第三个柱子上很困难,所以Gardon决定作个小弊,他又找来了一根一模一样的柱子,通过这个柱子来更快的把所有的盘子移到第三个柱子上。下面的问题就是:当Gardon在一次游戏中使用了N个盘子时,他需要多少次移动才能把他们都移到第三个柱子上?很显然,在没有第四个柱子时,问题的解是2^N-1,但现在有了这个柱子的帮助,又该是多少呢?

Input

包含多组数据,每个数据一行,是盘子的数目N(1<=N<=64)。

Output

对于每组数据,输出一个数,到达目标需要的最少的移动数。

Sample Input

1
3
12

Sample Output

1
5
81

CODE

#include<bits/stdc++.h>
int f[65];
int main()
{
	int k = 2, m = 2, j = 0;
	f[1] = 1;
	for (int i = 2; i < 65; ++i) {
		f[i] = f[i - 1] + k;
		++j;
		if (j == m) {
			j = 0;
			++m;
			k *= 2;
		}
	}
	int n;
	while (scanf("%d", &n) != EOF) {
		printf("%d\n", f[n]);
	}
}
汉诺塔III HDU - 2064

约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下、由小到大顺序串着由64个圆盘构成的塔。目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动一个盘,且不允许大盘放在小盘的上面。
现在我们改变游戏的玩法,不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到下盘的上面。
Daisy已经做过原来的汉诺塔问题和汉诺塔II,但碰到这个问题时,她想了很久都不能解决,现在请你帮助她。现在有N个圆盘,她至少多少次移动才能把这些圆盘从最左边移到最右边?

Input

包含多组数据,每次输入一个N值(1<=N=35)。

Output

对于每组数据,输出移动最小的次数。

Sample Input

1
3
12

Sample Output

2
26
531440

CODE

#include <bits/stdc++.h>
int main()
{
    unsigned long long dp[100], num = 6;
    memset(dp, 0, sizeof(dp));
    int n;
    dp[1] = 2;
    for (int i = 2; i < 65; i++){
        dp[i] = dp[i - 1] + num;
        num *= 3;
    }
    while (~scanf("%d", &n))
        printf("%lld\n", dp[n]);
    return 0;
}
汉诺塔IV HDU - 2077

还记得汉诺塔III吗?他的规则是这样的:不允许直接从最左(右)边移到最右(左)边(每次移动一定是移到中间杆或从中间移出),也不允许大盘放到小盘的上面。xhd在想如果我们允许最大的盘子放到最上面会怎么样呢?(只允许最大的放在最上面)当然最后需要的结果是盘子从小到大排在最右边。

Input

输入数据的第一行是一个数据T,表示有T组数据。
每组数据有一个正整数n(1 <= n <= 20),表示有n个盘子。

Output

对于每组输入数据,最少需要的摆放次数。

Sample Input

2
1
10

Sample Output

2
19684

CODE

#include <bits/stdc++.h>
int main()
{
    unsigned long long dp[100], num = 2;
    memset(dp, 0,sizeof(dp));
    dp[1] = 2;
    for (int i = 2; i < 65; i++){
        dp[i] = dp[i - 1] + num;
        num *= 3;
    }
    int n, k;
    scanf("%d", &n);
    while(n--){
        scanf("%d", &k);
        printf("%lld\n", dp[k]);
    }
    return 0;
}
为了在Windows安装ADB工具,你可以按照以下步骤进行操作: 1. 首先,下载ADB工具包并解压缩到你自定义的安装目录。你可以选择将其解压缩到任何你喜欢的位置。 2. 打开运行窗口,可以通过按下Win+R键来快速打开。在运行窗口中输入"sysdm.cpl"并按下回车键。 3. 在系统属性窗口中,选择"高级"选项卡,然后点击"环境变量"按钮。 4. 在环境变量窗口中,选择"系统变量"部分,并找到名为"Path"的变量。点击"编辑"按钮。 5. 在编辑环境变量窗口中,点击"新建"按钮,并将ADB工具的安装路径添加到新建的路径中。确保路径正确无误后,点击"确定"按钮。 6. 返回到桌面,打开命令提示符窗口。你可以通过按下Win+R键,然后输入"cmd"并按下回车键来快速打开命令提示符窗口。 7. 在命令提示符窗口中,输入"adb version"命令来验证ADB工具是否成功安装。如果显示版本信息,则表示安装成功。 这样,你就成功在Windows安装ADB工具。你可以使用ADB工具来执行各种操作,如枚举设备、进入/退出ADB终端、文件传输、运行命令、查看系统日志等。具体的操作方法可以参考ADB工具的官方文档或其他相关教程。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* [windows环境安装adb驱动](https://blog.csdn.net/zx54633089/article/details/128533343)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Windows安装使用ADB简单易懂教程](https://blog.csdn.net/m0_37777700/article/details/129836351)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值