河内双塔由经典的汉诺塔问题演变而来,双盘的增加并没有改变盘子的转移策略:仍然是,先借助目标盘把原盘上除了最大的两个盘子 移动至中间盘,再将原盘底部最大的两个盘子移动至目标盘,之后借助原盘将中间盘的所有盘子移动至目标盘;可直接采用单盘转移的写法,结果乘以2即可。
但这需要注意数据范围,递归体每次进入需要要进入两层,题目范围1-50,最坏执行2^50次,会超时,需要做个简单的优化。递归式的写法其实很多计算点都是重复的,可采用记忆化搜索,初始化f[55] = {0}, 如果f[i]不等于0就是被计算过的点,直接返回f[i],不进入递归体,可以大幅低复杂度。写法如下:
#include <iostream>
using namespace std;
typedef long long LL;
LL f[55];
LL hannuo(char sou, char temp, char des, int n)
{
if (f[n]) return f[n];
f[n] += hannuo(sou, des, temp, n - 1);
f[n] ++ ;
f[n] += hannuo(temp, sou, des, n - 1);
return f[n];
}
int main()
{
int n;
cin >> n;
f[1] = 1; // 初始化1个圆盘的转移次数
cout << 2 * hannuo('a', 'b', 'c', n) << endl;
return 0;
}