四柱汉诺塔 -- 动态规划求解最优移动次数

自己用Java写了一个前台进行四柱汉诺塔的移动演示,是按照最优次序进行移动的,链接里有详细的代码实现:https://download.csdn.net/download/qq_40285036/10841684

1.问题描述

四柱汉诺塔,在A柱上有N个盘子,**最少**经过多少次移动能把盘子全部移动到D上?

四柱汉诺塔

2.问题分析

  1. 先来回顾一下三柱汉诺塔,对于三柱汉诺塔问题,他的移动次数是固定的,若有N个盘子,那么移动次数就是2^N - 1。
  2. 四柱汉诺塔多了一柱,所以移动次序变为
    (1)先把k个盘子,从A柱经过C,D移动到B上。
    (2)再把A柱上的N-K个盘子,经过C,移动到D上(这个子问题就是三柱汉诺塔问题,他的移动次数为2^(n-k) - 1。)
    (3)再把k个盘子,从B柱上经过A,C移动到D上。
    3.从刚才的分析不难看出,我们起初先向B柱上移动的K个盘子决定了我最终的移动次数,所以目标是找到一个最优解K,使我最终的移动次数最小。

3.最优子结构

令dp[ n ]表示有n个盘子时的最优值,从2的分析中可以看出
(1)先把k个盘子,从A柱经过C,D移动到B上。–>移动次数为 dp[ k ]
(2)再把A柱上的N-K个盘子,经过C,移动到D上(这个子问题就是三柱汉诺塔问题,他的移动次数为2^(n-k) - 1。)–>移动次数为 2^(n-k) - 1
(3)再把k个盘子,从B柱上经过A,C移动到D上。 –> 移动次数为dp[ k ]

那么: dp[ n ] = 2 * dp[ k ] + 2^(n-k) - 1
枚举K值求最优,则最优子结构为:dp[ n ] = min(2 * dp[ k ] + 2 ^ (n - k) - 1), k = 1 … n
初始化 : dp[1] = 1(只有一个盘子,只需要一次移动);dp[2] = 3(两个盘子至少要移动三次)

4.代码

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>

using namespace std;

#define N 100
#define INF 0x3f3f3f3f

typedef long long ll;
ll dp[N];
int optimalPath[N];

void TraceBack(vector<int> &path,int n)
{
	if (optimalPath[n] == n)
	{
		path.push_back(n);
		return;
	}
	path.push_back(optimalPath[n]);
	TraceBack(path, optimalPath[n]);
	
}


int main()
{
	int n;
	while (cin >> n, n)
	{
		for (int i = 1; i <= n; i++)
			dp[i] = INF;
		dp[1] = 1;
		dp[2] = 3;

		for (int i = 3; i <= n; i++)
		{
			for (int k = 1; k <= i; k++)
			{
				ll tmp = 2 * dp[i - k] + (ll)pow(2, k) - 1;
				if (dp[i] > tmp)
				{
					dp[i] = tmp;
					optimalPath[i] = k;
				}
			}
		}
		cout << "最优移动次数为: " << dp[n] << endl;
		vector<int> path;
		TraceBack(path, n);
		cout << "optimal path:" << endl;
		for (int i : path)
		{
			cout << i << " ";
		}
		cout << endl;
	}
}

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 离散数学中的四柱汉诺塔问题是一个经典的递归问题。在传统的三柱汉诺塔问题中,我们有三根柱子:起始柱(A),辅助柱(B)和目标柱(C)。而在四柱汉诺塔问题中,我们有四根柱子:起始柱(A),中间柱(B),辅助柱(C)和目标柱(D)。 找到四柱汉诺塔问题的k可以通过递归的方式来解决,具体的步骤如下: 1. 首先,我们需要明确的是在三柱汉诺塔问题中,我们将移动n个盘子需要进行2^n - 1次移动。在四柱汉诺塔问题中,我们需要进行k次移动。 2. 当n=1时,只有一个盘子需要移动。我们可以直接将它从起始柱A移动到目标柱D,完成第一次移动。 3. 当n>1时,我们可以将问题分解为多个子问题。每次将n个盘子分成两部分:第一部分由1个盘子组成,第二部分由n-1个盘子组成。我们需要进行k次移动。首先将n-1个盘子通过递归的方式从A柱移到C柱上,完成k次移动。然后,将第k次移动时的盘子从A柱移到D柱,完成第k次移动。再将n-1个盘子从C柱移回到A柱上,完成k次移动。最后将第k次移动时的盘子从D柱移到C柱上,完成最后一次移动。 4. 如此递归下去,直到n=1时,问题得以解决。 综上所述,我们可以通过递归的方式来解决四柱汉诺塔问题,并找到k次移动的方法。 ### 回答2: 离散数学中,四柱汉诺塔是一种将圆盘从一根柱子移动到另一根柱子的数学问题。在四柱汉诺塔中,我们有四根柱子,标记为A、B、C、D,以及n个不同大小的圆盘,初始状态下所有的圆盘都在柱子A上。 想要找到四柱汉诺塔的k,我们可以借助递归思想进行分析。假设目标是将n个圆盘从柱子A移动到柱子B上。首先,我们可以将这个问题简化为将n-1个圆盘从柱子A移动到柱子C上,同时保持柱子D为空柱子。 接下来,我们将n号圆盘从柱子A移动到柱子D上,以便为后续操作让出空间。然后,我们将n-1个圆盘从柱子C移动到柱子D上,同时保持柱子B为空柱子。 最后,我们将n号圆盘从柱子D移动到柱子B上。至此,我们成功将n个圆盘从柱子A移动到柱子B上。 通过以上的递归思想,我们可以找到四柱汉诺塔的k。具体步骤如下: 1. 当n=1时,直接将圆盘从柱子A移动到柱子B上,此时k=1。 2. 当n>1时,将n-1个圆盘从柱子A移动到柱子C上,同时保持柱子D为空柱子。此时,k为n-1个圆盘的汉诺塔问题的k。 3. 将n号圆盘从柱子A移动到柱子D上,此时k增加1。 4. 将n-1个圆盘从柱子C移动到柱子D上,同时保持柱子B为空柱子。此时,k为n-1个圆盘的汉诺塔问题的k。 5. 将n号圆盘从柱子D移动到柱子B上,此时k增加1。 根据以上的步骤,我们可以找到四柱汉诺塔的k。 ### 回答3: 离散数学中的四柱汉诺塔问题是指在四个柱子上将一堆盘子从柱子A移动到柱子D,其中每个盘子的大小都不同,且较大的盘子不能放在较小的盘子上面。要找到这个问题中的k,我们可以使用递归的方法来解决。 首先,我们需要理解汉诺塔问题的递推关系。对于n个盘子的汉诺塔问题,我们可以将其划分为两个子问题:将n-1个盘子从柱子A移动到柱子C,再将第n个盘子从柱子A移动到柱子D,最后将n-1个盘子从柱子C移动到柱子D。这里,我们可以将移动过程看作一个递归过程。 对于四柱汉诺塔问题,我们可以将其划分为三个子问题:将n-1个盘子从柱子A移动到柱子C,再将第n个盘子从柱子A移动到柱子D,最后将n-1个盘子从柱子C移动到柱子D。因此,我们可以得到递推公式如下: F(n) = 2F(n-1) + 1 其中,F(n)表示n个盘子的最少移动次数。通过这个递推公式,我们可以求解出每个n值对应的最少移动次数。 具体来说,我们可以使用循环来计算F(n)的值。当n等于1时,F(n)等于1;当n大于1时,使用循环从n-1开始递减计算F(n)的值,直到n递减至1为止。最后得到的F(n)即为所求的k。 总结起来,离散数学四柱汉诺塔问题中的k值可以通过递推关系 F(n) = 2F(n-1) + 1 计算得出,其中n为盘子的数量。通过循环计算可以求解出每个n值对应的最少移动次数,进而找到k值。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值