参考博客:http://blog.csdn.net/u014135021/article/details/50995386
汉诺塔的递推核心代码为
a[1]=1;
for(int i=2;i<=n;i++)
a[i]=2*a[I-1]+1;
由递归算法可知,我们要想把A塔上n个盘子挪到C盘
1先把n-1个盘子挪到B盘
2把第n个盘子挪到C盘
3n-1个盘子挪到c盘
1和3步骤近似相同,只是借助的塔不一样。我们不妨开一个数组a,a[I]表示移动I个盘子所需要步数,我们可知第一步对应的步数为a[n-1],所以得到上面的递推公式
汉诺塔IX
HDU - 2175
1,2,...,n表示n个盘子.数字大盘子就大.n个盘子放在第1根柱子上.大盘不能放在小盘上. 在第1根柱子上的盘子是a[1],a[2],...,a[n]. a[1]=n,a[2]=n-1,...,a[n]=1.即a[1]是最下 面的盘子.把n个盘子移动到第3根柱子.每次只能移动1个盘子,且大盘不能放在小盘上. 问第m次移动的是那一个盘子.
Input每行2个整数n (1 ≤ n ≤ 63) ,m≤ 2^n-1.n=m=0退出Output输出第m次移动的盘子的号数.Sample Input
63 1 63 2 0 0
Sample Output
1 2
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
long long n, m;
long long a[65], b[65];
void init()
{
a[1] = 1;
b[1] = 2;
b[0] = 1;
for(int i = 2; i <= 63; i ++)
{
a[i] = a[i - 1]*2 + 1;
b[i] = a[i] + 1;
}
}
int sove()
{
if(m == a[63])
return 1;
while(m > 0)
{
int t = 0;
while(m > b[t])
{
t ++;
}
if(m == b[t])
return t + 1;
m -= b[t - 1];
}
}
int main()
{
init();
while(scanf("%lld %lld", &n, &m) != EOF)
{
if(n == 0&&m == 0)
break;
printf("%d\n", sove());
}
return 0;
}