uva 10254 - The Priest Mathematician(dp)

来源:互联网 发布:php权限功能模块 编辑:程序博客网 时间:2024/05/16 23:40

题目链接:uva 10254 - The Priest Mathematician


题目大意:四根柱子的汉诺塔问题,问说移动的最少次数。


解题思路:一开始想着说用两个大数数组f[N], b[N], 然后一定存在一个值k,使得f[i] = f[k] * 2 + b[i - k]最小,然后b[i] = b[i - 1] * 2+ 1,但是这样枚举k的计算量非常大。

然后参考别人打表找出来的规律,每次增长的个数为2个2^1,3个2^2,4个2^3.....m - 1个2^m。


#include <stdio.h>#include <string.h>#define max(a,b) (a)>(b)?(a):(b)const int N = 10005;const int M = 400;int n, f[N][M], d[M];void put(int c[]) {for (int i = c[0]; i; i--)printf("%d", c[i]);printf("\n");}void mul(int c[]) {int sum = 0;for (int i = 1; i <= c[0]; i++) {sum += c[i] * 2;c[i] = sum %  10;sum /= 10;}while (sum) {c[++c[0]] = sum % 10;sum /= 10;}}void add(int ans[], int a[], int b[]) {int sum = 0;ans[0] = max(a[0],  b[0]);for (int i = 1; i <= ans[0]; i++) {if (i <= a[0]) sum += a[i];if (i <= b[0]) sum += b[i];ans[i] = sum % 10;sum /= 10;}while (sum) {ans[++ans[0]] = sum % 10;sum /= 10;}}void init() {f[1][0] = f[1][1] = d[0] = 1;d[1] = 2;int c = 0, top = 2;for (int i = 2; i <= 10000; i++) {add(f[i], f[i - 1], d);c++;if (c == top) {top++, c = 0;mul(d);}}}int main () {init();while (scanf("%d", &n)  == 1) {if (n)put(f[n]);else printf("0\n");}return 0;}