Strange Towers of Hanoi

81 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题意:四根柱子的汉诺塔问题,依次输出圆盘个数为1~12的最少移动次数。

汉诺塔问题比较经典,先介绍一下三根柱子的汉诺塔问题,假如有A,B,C三根柱子,初始条件下A柱子上有n个圆盘,我们需要求将A柱子上的圆盘全部移动到C柱子上的最少移动次数。不难想到的是我们要移动A柱子上的最后一个圆盘,必定要把前n-1个圆盘全部移动到B柱子上,才能把第n个圆盘移动到C柱子上,将n-1个圆盘全部移动到B柱子上所需的最少移动次数为f[n-1],将第n个圆盘移动到C柱子上的次数为1,再将B柱子上的n-1个圆盘借助A柱子全部移动到C柱子上的最少移动次数依旧是f[n-1],所以就有递推式f[n]=f[n-1]*2+1,利用这个递推式我们能比较容易地得出f[n]=2^n-1。(在代码中我就不再计算了,直接利用这个结论了)

三根柱子的汉诺塔问题解决了,下面我们来看下四根柱子的汉诺塔问题,假设四根柱子依次为A,B,C,D,在处理四根柱子的汉诺塔问题时,我们必经的一种状态就是我们需要先将A柱子上的i个圆盘借助C,D两根柱子移动到B柱子上,所需最少次数为dp[i],然后我们就是将A柱子上剩余的n-i个圆盘借助柱子C移动到D柱子上,所需最少次数为f[n-i],最后再将B柱子上的i个圆盘借助A,C两根柱子移动到D柱子上,所需最少移动次数为dp[i],总的移动次数就是f[n-i]+2d[i],我们需要遍历1~n找一个使得f[n-i]+2d[i]值最小的i作为最优结果,这样就可以完成四根柱子的汉诺塔问题的求解了。同理n根柱子的汉诺塔问题也是先转化为n-1根柱子的汉诺塔问题进行求解的。

下面是代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<cmath>
using namespace std;
int f[15];
int main()
{
	memset(f,0x3f,sizeof f);//不要忘记初始化 
	f[0]=0;
	for(int i=1;i<=12;i++)
	{
		for(int j=0;j<i;j++)
			f[i]=min(f[i],2*f[j]+(1<<(i-j))-1);
		printf("%d\n",f[i]);
	}
	return 0;
}