【题目描述】
给定A、B、C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形)。现要将这些圆盘移到C柱上,在移动过程中可放在B柱上暂存。要求:
(1)每次只能移动一个圆盘;
(2)A、B、C三根细柱上的圆盘都要保持上小下大的顺序;
任务:设An为2n个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出An。
【输入格式】
一个正整数n,表示在A柱上放有2n个圆盘。
【输出格式】
仅一行,包含一个正整数, 为完成上述任务所需的最少移动次数An。
【样例输入】
样例输入1 | 样例输入2 |
1 | 2 |
【样例输出】
样例输出1 | 样例输出2 |
2 | 6 |
【分析】
设f[n]为有2 * n个圆盘,所需移动的步数。
分三步:
- 将2 * n - 2个盘子移动到B,所用的步数是f[n – 1]
- 将最后的两个移动到C上,所用步数是2
- 将2 * n - 2个盘子移动到C,所用的步数是f[n – 1]
那么f[n] = 2 * f[n – 1] + 2;
f[n] + 2 = 2 * (f[n – 1] + 2);
f[n] = 2 ^ (n + 1) – 2;
然后就是高精度了。
#include <stdio.h>
#include <string.h>
#define MAXLEN 110
#define BASE 10000
int ans[MAXLEN],b[MAXLEN];
int n;
void cheng1(int a[]) {
int c[MAXLEN];
memset(c,0,sizeof(c));
for (int i = 1;i <= a[0];++i)
for (int j = 1;j <= a[0];++j) {
int x = i + j - 1;
c[x] += a[i] * a[j];
c[x + 1] += c[x] / BASE;
c[x] %= BASE;
}
c[0] = a[0] * 2;
for (int i = 1;i <= c[0];++i) {
c[i + 1] += c[i] / BASE;
c[i] %= BASE;
}
while (c[c[0] + 1])
++c[0];
while ((!c[c[0]]) && (c[0] > 1))
--c[0];
for (int i = 0;i < MAXLEN;++i)
a[i] = c[i];
}
void cheng2(int a[]) {
int c[MAXLEN];
memset(c,0,sizeof(c));
for (int i = 1;i <= a[0];++i)
c[i] = a[i] * 2;
c[0] = a[0] + 1;
for (int i = 1;i <= c[0];++i) {
c[i + 1] += c[i] / BASE;
c[i] %= BASE;
}
while (c[c[0] + 1])
++c[0];
while ((!c[c[0]]) && (c[0] > 1))
--c[0];
for (int i = 0;i < MAXLEN;++i)
a[i] = c[i];
}
void pow2(int x) {
if (x == 1)
return;
pow2(x / 2);
cheng1(ans);
if (x & 1)
cheng2(ans);
}
int main() {
scanf("%d",&n);
ans[0] = 1;
ans[1] = 2;
++n;
pow2(n);
if (ans[1] >= 2)
ans[1] -= 2;
else {
int now = 1;
while (!ans[now + 1])
++now;
for (int i = now;i > 0;--i) {
--ans[i + 1];
ans[i] += BASE;
}
ans[1] -= 2;
}
printf("%d",ans[ans[0]]);
for (int i = ans[0] - 1;i > 0;--i)
printf("%d%d%d%d",ans[i] / 1000,
ans[i] / 100 % 10,
ans[i] / 10 % 10,
ans[i] % 10);
return 0;
}