汉诺塔
问题链接: https://www.jisuanke.com/course/2291/182230
问题分析:
参考博客:http://www.cnblogs.com/xxNote/p/3965739.html
- 先把n-1个盘子从A移动到B,剩下最大的那个盘子在A(这时所移动的次数为 f (n-1) )
- 再将最大的那个盘子移到C盘,(这时所移动的次数为 f (n-1) + 1 )
- 最后将那n-1个盘子从B移到C盘上,所移动的次数为 f (n-1) + 1 + f (n-1) )
- 递推公式:f (n) = f ( n - 1) * 2 + 1
- 通项公式:f (n) = 2 ^ n - 1
- long long 类型 或者 __int64
源代码
#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <stdint.h>
using namespace std;
long long step = 0;
long long t = 0;
long long f(long long n) //计算所消耗的体力
{
if(n == 1)
return 1;
else
return f(n-1)*2+n;
}
long long hanoi(long long n)
{
if(n == 1)
return 1;
else
return hanoi(n-1)*2+1;
}
int main()
{
long long n;
scanf("%lld", &n);
printf("%lld %lld\n", hanoi(n), f(n));
return 0;
}
汉诺塔III hdu 2064
问题链接:http://acm.hdu.edu.cn/showproblem.php?pid=2064
问题分析:
- 将n-1个盘子从A ----> C, 移动 a [n-1]
- 第n个盘子从A ----> B, 移动 1
- n-1个盘子再从 C ----> A, 移动 a [n-1]
- 第n个盘子从 B ----> C,移动 1
- 最后n-1个盘子从 A ----> C,移动 a [n-1]
- 总共移动 3*a[n-1] + 2
源代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
long long a[50];
int main()
{
a[0] = 0;
for(int i = 1; i <= 35; i++)
a[i] = 3*a[i-1]+2;
int n;
while(scanf("%d", &n) != EOF)
printf("%lld\n", a[n]);
return 0;
}
汉诺塔VI hdu 1996
问题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1996
问题分析:
- 类似于高中的5封信投到3个信箱中,共有3^5中投法
- 此题为n个盘子放到3个柱子上,所以共有3^n种
- 使用快速幂
- 快速幂模板
// a的b次方 int pow(int a, int b) { int ans = 1, base = a; while (b != 0) { if (b & 1) ans *= base; base *= base; b >>= 1; } return ans; }
源代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
long long fast(long long x, long long n) //快速幂
{
long long res = 1;
while(n>0)
{
if(n&1)
res= res*x;
x = x*x;
n >>= 1;
}
return res;
}
int main()
{
long long t;
scanf("%lld", &t);
while(t--)
{
long long n;
scanf("%lld", &n);
long long sum = fast(3, n);
printf("%lld\n", sum);
}
return 0;
}