题目链接
http://poj.org/problem?id=1958
分析
对于 n n n 个圆盘 3 3 3 座塔的情况我们是熟悉的,由于只有 3 3 3 座塔,且小盘必须在大盘上面,所以操作过程可以概括为先将 n − 1 n - 1 n−1 个盘子借助 C C C 塔从 A A A 塔移动到 B B B 塔,再将最底层的盘子移动到 C C C 盘,再将 B B B 塔上的 n − 1 n - 1 n−1 个盘子借助 A A A 塔移动到 C C C 塔,这和先前一样,因此,若设 d [ n ] d[n] d[n] 表示 n n n 个圆盘 3 3 3 座塔的移动步数,则 d [ n ] = 2 ∗ d [ n − 1 ] + 1 d[n] = 2 * d[n - 1] + 1 d[n]=2∗d[n−1]+1;类比到 4 4 4 座塔,可在四塔模式下将若干个盘子移动到 B B B 塔,再在三塔模式下借助 C C C 塔将其余盘子移动到 D D D 塔,最后在四塔模式下将 B B B 塔上的盘子移动到 D D D 塔,枚举开始将多少盘子移动到 B B B 塔,在所得步数中取最小值即可;由此可以推广到 n n n 个盘子 m m m 座塔时所需的最少移动步数。
AC代码
#include <cstdio>
#include <cstring>
const int maxn = 15;
int d[maxn], f[maxn];
int main() {
for (int i = 1; i <= 12; ++i) d[i] = 2 * d[i - 1] + 1;
memset(f, 0x3f, sizeof(f));
f[1] = 1;
for (int i = 2; i <= 12; ++i)
for (int j = 1; j < i; ++j)
if (2 * f[j] + d[i - j] < f[i]) f[i] = 2 * f[j] + d[i - j];
for (int i = 1; i <= 12; ++i) printf("%d\n", f[i]);
return 0;
}