3-7四柱汉诺塔问题(动态规划)

本文介绍了一种解决四柱汉诺塔问题的算法,并通过动态规划方法计算最少移动次数。文章提供了详细的分析过程和C++实现代码。

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

一、题目

3-7四柱汉诺塔问题

四柱汉诺塔要求同三柱汉诺塔,只不过多了一个辅助柱子。计算n个盘子由a柱借助c和d柱移动到b柱上的最少移动次数。
如图:
请添加图片描述

二、分析

1、分析最优子结构性质

该问题可将a柱上的n个盘子分为上下两部分,下半部分k个盘子,上半部分n-k个盘子。
移动步骤如下∶
(1)将a柱前n-k个盘子借助b,c移动到d ( n-k个盘子四柱汉诺塔问题)
(2)将a柱剩余的k个盘子借助c移动到b ( k个盘子的三柱汉诺塔问题)
(3)将d柱n-k个盘子借助a、c柱移动到b ( n-k个盘子四柱汉诺塔问题)
由此可见:
n个盘子的四柱汉诺塔问题可转化为2个n-k个盘子的四柱汉诺塔问题和1个k个盘子三柱汉诺塔问题(移动次数已知为2^k-1)。
因此该问题满足最优子结构性质。即大问题的最优解包含子问题的最优解。

2、最少移动次数的递归定义

设n个盘子的四柱汉诺塔的最少移动次数为f(n )
(1)当n=0时,移动次数为0
(2)当n=1时,移动次数为1
(3)当n>1时,f (n ) =2f ( n-k ) +2^k-1 在0<k<n范围的最小值
在这里插入图片描述

3、求最优值-时间复杂性O(n2)

int Fn(int n){
	f[0]=0;//0个盘子移动次数是0 
	f[1]=1;//1个盘子移动次数是1 
	for(int i=2;i<=n;i++){  //把盘子数i从2加到n 
		f[i]=2*f[i-1]+1;  //把盘子数分为i-1和1 ,初始化f[i]=2*f[i-1]+1
		for(int k=2;k<i;k++){  //盘子数分为i-k和k
			int t=2*f[i-k]+exp2(k)-1;
			if(t<f[i])
			f[i]=t;
		}
	}
} 

三、代码

//3-7四柱汉诺塔问题 (动态规划) 
#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std; 
int f[100];//f[i]是四个柱子下i个盘子移动的次数
//四柱汉诺塔问题: a上面有n个盘子,有a,b,c,d四个个柱子,要求把a上面的n个盘子移到b上 
int Fn(int n){
	f[0]=0;//0个盘子移动次数是0 
	f[1]=1;//1个盘子移动次数是1 
	for(int i=2;i<=n;i++){  //把盘子数i从2加到n 
		f[i]=2*f[i-1]+1;  //把盘子数分为i-1和1 ,初始化f[i]=2*f[i-1]+1
		for(int k=2;k<i;k++){  //盘子数分为i-k和k
			int t=2*f[i-k]+exp2(k)-1;
			if(t<f[i])
			f[i]=t;
		}
	}
} 
int cnt=0;//记录移动次数 
//顺便复习一下 三柱汉诺塔问题 (递归)
// a上面有n个盘子,有a,b,c三个柱子,要求把a上面的n个盘子移到b上 
void hanoi(int n,int a,int b,int c){//三柱汉诺塔问题 n个盘子的移动次数是2^n-1 
	if(n>0){
		hanoi(n-1,a,c,b);  //把a上面的n-1个盘子移到c上面 
		cnt++;// move(a,b);  把a上面的最后一个盘子移到b上 
		hanoi(n-1,c,b,a);  //把c上面的n-1个盘子移到b上面 
	}
	else return; 
} 
int main(){
	int n;//n个盘子
	int a=0,b=0,c=0;
	//cin>>n;
	n=4;
	Fn(n);
	cout<<n<<"个盘子,四柱移动次数是"<<f[n]<<endl;
	a=n;
	hanoi(n,a,b,c);
	cout<<n<<"个盘子,三柱移动次数是"<<cnt<<endl;
	return 0;
}

四、运行截图

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清木!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值