汉诺塔
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次移动的是哪一个盘子,从哪根柱子移到哪根柱子.
例如:n=3,m=2.回答是 :2 1 2,即移动的是2号盘,从第1根柱子移动到第2根柱子.
参考题目链接:
HDU 2511 汉诺塔 X
/*
* 汉诺塔
* 一号柱有n个盘子,叫做源柱.移往3号柱,叫做目的柱.2号柱叫做中间柱.
* 全部移往3号柱要f(n)=(2^n)-1次.
* 最大盘n号盘在整个移动过程中只移动一次,n-1号移动2次,i号盘移动2^(n-i)次.
* 1号盘移动次数最多,每2次移动一次.
* 第2k+1次移动的是1号盘,且是第k+1次移动1号盘.第4k+2次移动的是2号盘,且是第k+1次移动2号盘.
* 第(2^s)k+2^(s-1)移动的是s号盘,这时s号盘已被移动了k+1次.每2^s次就有一次是移动s号盘.
* 第一次移动s号盘是在第2^(s-1)次.
* 第二次移动s号盘是在第2^s+2^(s-1)次.
* ......
* 第k+1次移动s号盘是在第k*2^s+2^(s-1)次.1--2--3--1叫做顺时针方向,1--3--2--1叫做逆时针方向.
* 最大盘n号盘只移动一次:1--3,它是逆时针移动.
* n-1移动2次:1--2--3,是顺时针移动.
* 如果n和k奇偶性相同,则k号盘按逆时针移动,否则顺时针.
*/
int main()
{
int i, k;
scanf("%d", &k);
for (i = 0; i < k; i++)
{
int n, l;
__int64_t m, j;
__int64_t s, t;
scanf("%d%lld", &n, &m);
s = 1;
t = 2;
for (l = 1; l <= n; l++)
{
if (m % t == s)
{
break;
}
s = t;
t *= 2;
}
printf("%d ", l);
j = m / t;
if (n % 2 == l % 2)
{ // 逆时针
if ((j + 1) % 3 == 0)
{
printf("2 1\n");
}
if ((j + 1) % 3 == 1)
{
printf("1 3\n");
}
if ((j + 1) % 3 == 2)
{
printf("3 2\n");
}
}
else
{ // 逆时针
if ((j + 1) % 3 == 0)
{
printf("3 1\n");
}
if ((j + 1) % 3 == 1)
{
printf("1 2\n");
}
if ((j + 1) % 3 == 2)
{
printf("2 3\n");
}
}
}
return 0;
}