首先回忆经典的汉诺塔问题:n个盘子3个塔,最开始都叠在第一个塔上,要变换到第三个塔。
有一个经典也是最优的解决方法,每次先把上面n-1个盘子塔移到2塔上(2个塔可用),再把第n个盘子移到3塔,再把上面n-1个盘子移到3塔(2个塔可用)。这样我们得到了递推关系式:(f_n = 2*f_{n - 1} + 1)。
当塔数增加为4时,我们有了更多的选择。我们不必每次都移走上面n-1个盘子,而是可以先借助1,2,3,4四个塔柱移走n-k个盘子到2塔,剩下k个盘子依然有3,4两个空塔柱可以用来转移。因为下面的盘子比较大,在目标状态中也是底端的盘子,我们采用3个塔的方式借助1,3,4三个柱子把他们移到4柱。再借助1,2,3,4四个柱子把上面n-k个盘子从2塔移到4塔。得到递推式:(g_n = min {2 * g_{k} + f_{n - k}})。
#include <bits/stdc++.h>
using namespace std;
const int N = 15;
int f[N], g[N];
int main () {
f[1] = 1;
for (int i = 2; i <= 12; ++i) {
f[i] = f[i - 1] * 2 + 1;
g[i] = 0x3f3f3f3f;
}
g[1] = 1;
for (int i = 2; i <= 12; ++i) {
int min_ans = 0x3f3f3f3f;
for (int k = 0; k <= i; ++k) {
g[i] = min (g[i], 2 * g[i - k] + f[k]);
}
}
for (int i = 1; i <= 12; ++i) {
cout << g[i] << endl;
}
}
在时间复杂度可以接受的前提下,上述做法可以推广到n盘m塔的计算!