Towers of Hanoi

Towers of Hanoi
汉诺塔问题与汉诺塔四塔问题
标签(空格分隔): ACM 算法


最常见的汉诺塔问题:
汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?

这是最简单的汉诺塔问题,从题目中我们了解到小圆盘上都不能放置大圆盘所以无论我们在a柱上放有多少个圆盘,我们必须首先把a柱最下面也是最大的盘子放到C柱上,那我们就要把n-1个柱子放到B柱上,由此我们可以设d[n]是放n个盘子的最少次数,则我们可以得公式
d[n]=2*d[n-1]+1 即把n-1个柱子从A柱上移到B柱上,然后再把第n个柱子移到c柱上,最后再把B柱上的n-1个柱子移到C柱上.

到了汉诺塔四塔问题。变成4座塔n个盘子最少次数得问题了。这就变成了另一个问题了。
多柱汉诺塔问题可以Frame–Stewart算法来解决。
算法描述:
The Frame–Stewart algorithm, giving a presumably optimal solution for four (or even more) pegs, is described below:

Let n be the number of disks.
Let r be the number of pegs.
Define T(n,r) to be the minimum number of moves required to transfer n disks using r pegs
The algorithm can be described recursively:

For some k, 1 \leq k < n, transfer the top k disks to a single peg other than the start or destination pegs, taking T(k,r) moves.
Without disturbing the peg that now contains the top k disks, transfer the remaining n-k disks to the destination peg, using only the remaining r-1 pegs, taking T(n-k,r-1) moves.
Finally, transfer the top k disks to the destination peg, taking T(k,r) moves.
The entire process takes 2T(k,r)+T(n-k,r-1) moves. Therefore, the count k should be picked for which this quantity is minimum.

This algorithm (with the above choice for k) is presumed to be optimal, and no counterexamples are known.
翻译过来就是
对于四塔汉诺塔
1.把A柱上的n个盘子分为上下两个部分,上面k个盘子,下面n-k个盘子
2.把上面的k个盘子经过C,D转移到B柱上
3.这样剩下的n-k个盘子就转化为三柱汉诺塔问题了,经c柱转移到d柱子上
4.再对那k个盘子用三柱汉诺塔来解决
我们可以设f[k]为四柱汉诺塔问题转移k个盘子所用的最少步数
则我们可以得到公式
f[n]=min{2*f[i]+d[n-i]} 其中f1=1,1 <= i < n.
这种可以推广到n盘m塔问题
引入一道例题
POJ 1958
code:

 #include<bits/stdc++.h>
using namespace std;
const int maxn=9999999;
int f[100],d[100];
int main()
{
	int n;
	n=12;
	memset(f,maxn,sizeof(f));
	memset(d,0,sizeof(d));
	f[1]=1;
	for(int i=1;i<=n;i++)
		d[i]=2*d[i-1]+1;
	int minn=maxn;
	for(int i=1;i<=n;i++)
	{
		for(int k=1;k<i;k++)
			f[i]=min(2*f[k]+d[i-k],f[i]);
	}
	for(int i=1;i<=n;i++)
	{
		cout<<f[i]<<endl;
	}
}

参考博客:
hanoi

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值