uva 10254 - The Priest Mathematician(dp)

题目链接: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;
}


你可能感兴趣的:(uva 10254 - The Priest Mathematician(dp))