点击打开链接1207
现在有四根柱子(A,B,C,D),其他规则不变。我们的目标是将n个盘移到D上,所以我们首先将n-1个盘移到B、C上,然后将第n个盘移到D上。我们令从A->D需要F(n)步,下面分为三步实现:
所以一共需要F(n) = 2*F(r) + 2^(n-r) - 1步。对于不同的r,F(n)不同。我们采用循环的方式,对r进行遍历,用min标记F(n)最小值。求得min[ 2*F(r) + 2^(n-r) - 1] (1 <= r < n)
#include <stdio.h> #include <math.h> #define MAX 70 #define INF 99999999 long long hanoi2(int); int main() { int n; long long res; while (scanf("%d", &n) != EOF) { if (n < 1 || n > 64) break; res = hanoi2(n); printf("%lld\n", res); } return 0; } long long hanoi2(int n) { long long a[MAX] = { 0, 1, 3 }; long long min; int i, j; for (i = 3; i <= n; i++) { min = INF; //作为哨兵,初始化应该放在第一个循环内,这样第二个循环才能顺利执 for (j = 1; j < i; j++) { /* 一定要转换为unsigned,否则当n=64时,结果会溢出 */ if(min > 2*a[j] + (unsigned long long )pow(2, i-j) - 1) min = 2*a[j] + (unsigned long long )pow(2,i-j) - 1; } a[i] = min; } return a[n]; }
点击打开链接 2064
这道题很简单。我们令将n个盘从A->B需要F(n)步。下面分三步进行:
所以F(n) = 3*F(n-1) + 2步,有通项公式 f(n) = 3^n - 1
int main() { int n, i; long long res; while (scanf("%d", &n) != EOF) { if (n < 1 || n > 35) break; res = 2; if (n == 1) printf("%lld\n", res); else { for (i = 2; i <= n; i++) { res = 3*res + 2; } printf("%lld\n", res); } } return 0; }
点击打开 2077
这道题是2064汉诺塔3的变形。我们分三步实现:
F(n) = 2 * g(n-1) + 2.所以题目转化为只要求g(n)的递推式,或者通项公式即可。
为了实现1,我们需要将上面n-2个盘子从A-B-C(这就是汉诺塔3的问题),再将第n-1个盘子从A-B。然后,再将上面n-2个盘子从C-B。有,g(n-1) = 3^(n-2)-1 + 1 + g(n-2) ,从而有g(n) = (3^n - 1)/2。
所以,F(n) = 3^(n-1) + 1
#include <stdio.h> #include <math.h> int main() { int n, t; long long res, temp; while (scanf("%d", &t) != EOF) { while(t--) { scanf("%d", &n); if (n < 1 || n > 20) break; res = (long long) pow (3, n - 1) + 1; printf("%lld\n", res); } } return 0; }
点击打开1995
分析
这道题最水了。不要被表面假象所唬住。
假设有64个盘子,我们先看第64个盘子,它只需要移动1次;第63个盘子移动两次,前一次是为地64个盘子移的;第62个盘子移动4次,前两次是为第64个盘子移的,第三次是为了第63个盘子移的;。。。
可以看出规律第k个盘子移动了 2^(n-k)次。
代码
#include <stdio.h> #include <math.h> int main() { int t, n, k; long long res; while (scanf("%d", &t) != EOF) { while (t--) { scanf("%d %d", &n, &k); if ( k >= 1 && k <= n && n <= 60) { res = (long long) pow (2, n-k); printf("%lld\n", res); } } } return 0; }