汉诺塔II
Problem Description
经典的汉诺塔问题经常作为一个递归的经典例题存在。可能有人并不知道汉诺塔问题的典故。汉诺塔来源于印度传说的一个故事,上帝创造世界时作了三根金刚石柱子,在一根柱子上从下往上按大小顺序摞着64片黄金圆盘。上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一回只能移动一个圆盘。有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。也有人相信婆罗门至今仍在一刻不停地搬动着圆盘。恩,当然这个传说并不可信,如今汉诺塔更多的是作为一个玩具存在。Gardon就收到了一个汉诺塔玩具作为生日礼物。
Gardon是个怕麻烦的人(恩,就是爱偷懒的人),很显然将64个圆盘逐一搬动直到所有的盘子都到达第三个柱子上很困难,所以Gardon决定作个小弊,他又找来了一根一模一样的柱子,通过这个柱子来更快的把所有的盘子移到第三个柱子上。下面的问题就是:当Gardon在一次游戏中使用了N个盘子时,他需要多少次移动才能把他们都移到第三个柱子上?很显然,在没有第四个柱子时,问题的解是2^N-1,但现在有了这个柱子的帮助,又该是多少呢?
Gardon是个怕麻烦的人(恩,就是爱偷懒的人),很显然将64个圆盘逐一搬动直到所有的盘子都到达第三个柱子上很困难,所以Gardon决定作个小弊,他又找来了一根一模一样的柱子,通过这个柱子来更快的把所有的盘子移到第三个柱子上。下面的问题就是:当Gardon在一次游戏中使用了N个盘子时,他需要多少次移动才能把他们都移到第三个柱子上?很显然,在没有第四个柱子时,问题的解是2^N-1,但现在有了这个柱子的帮助,又该是多少呢?
Input
包含多组数据,每个数据一行,是盘子的数目N(1<=N<=64)。
Output
对于每组数据,输出一个数,到达目标需要的最少的移动数。
Sample Input
1 3 12
Sample Output
【思路分析】
多加了一根柱子的汉诺塔问题。设A,B,C,D四根柱子,要求把A上所有的盘子移到D上,求最少移动次数。一开始的思路受到三根柱子汉诺塔的束缚,即把上面(n - 2)个盘子借助C、D移动到B上,把第(n - 1)个盘子移到C上,把第n个盘子移到D上,再将第(n - 1)个盘子由C移到D上,最后把(n - 2)个盘子由B借助A、C移到D上。可是结果报WA。
原因是移动上面(n - i)(i从1到n - 1)个盘子的每一种情况都是不同的,不能仅仅通过(n - 2)个求最小移动次数,这样太片面了,需要从(n - 1)种情况选出一个最小值才是正确结果。
上述问题就是Frame算法:(设盘子总数为i)
1、把A的上面j个盘子借助C、D移到B —— hanoi[j]步
2、把A的剩余(i - j)个盘子通过C移到D(即三柱汉诺塔)—— 2 ^ (i - j) - 1 步
3、把B的j个盘子借助A、C移到D —— hanoi[j]步
最后,当j从1到(i - 1)时,上述三步之和的最小值就是i个盘子四柱汉诺塔的最终结果。递归方程为hanoi[i] = min(2 * hanoi[j] + 2 ^ (i - j) - 1)。
代码如下:
1
5
81
【思路分析】
多加了一根柱子的汉诺塔问题。设A,B,C,D四根柱子,要求把A上所有的盘子移到D上,求最少移动次数。一开始的思路受到三根柱子汉诺塔的束缚,即把上面(n - 2)个盘子借助C、D移动到B上,把第(n - 1)个盘子移到C上,把第n个盘子移到D上,再将第(n - 1)个盘子由C移到D上,最后把(n - 2)个盘子由B借助A、C移到D上。可是结果报WA。
原因是移动上面(n - i)(i从1到n - 1)个盘子的每一种情况都是不同的,不能仅仅通过(n - 2)个求最小移动次数,这样太片面了,需要从(n - 1)种情况选出一个最小值才是正确结果。
上述问题就是Frame算法:(设盘子总数为i)
1、把A的上面j个盘子借助C、D移到B —— hanoi[j]步
2、把A的剩余(i - j)个盘子通过C移到D(即三柱汉诺塔)—— 2 ^ (i - j) - 1 步
3、把B的j个盘子借助A、C移到D —— hanoi[j]步
最后,当j从1到(i - 1)时,上述三步之和的最小值就是i个盘子四柱汉诺塔的最终结果。递归方程为hanoi[i] = min(2 * hanoi[j] + 2 ^ (i - j) - 1)。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn = 65;
const int INF = 999999999;
int hanoi[maxn];
void solve()
{
hanoi[1] = 1;
hanoi[2] = 3;
for(int i = 3;i < maxn;i++)//打表
{
int minx = INF;
for(int j = 1;j < i;j++)
{
if((2 * hanoi[j] + pow(2,(i - j)) - 1) < minx)
{
minx = (2 * hanoi[j] + pow(2,(i - j)) - 1);
}
}
hanoi[i] = minx;
}
}
int main()
{
int n;
solve();
while(scanf("%d",&n) != EOF)
{
printf("%d\n",hanoi[n]);//查表
}
return 0;
}
本文探讨了四柱汉诺塔问题,分析了在额外柱子的帮助下移动圆盘的最少次数,并提供了优化算法求解过程。通过递归方程,解决了四柱汉诺塔问题,并给出了具体的实现代码。
1664

被折叠的 条评论
为什么被折叠?



