题目大意:
在正常的汉诺塔规则中再加一条:不允许直接把盘从1号柱移动到3号柱,也不允许直接把盘从3号柱移动到1号柱。初始状态为第0步,编程求在某步数时的状态。
思路:
如果把汉诺塔的变化打出来,那么就是这样的:
然后,就能发现:
1号圆盘在移动3次中,共移动了2次;2号圆盘在移动9次中,共移动了2次;3号圆盘在移动27次中,共移动了2次。
那么也就很容易推出:号圆盘每移动次中,会移动两次!
那么这道题就很好做了,预处理,每次可以利用周期问题求出答案。
时间复杂度:,最坏。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const char o[]={'1','2','3','2'};
int t,n,m,num[31],k;
int main()
{
scanf("%d",&t);
num[0]=1;
for (int i=1;i<=19;i++)
num[i]=num[i-1]*3; //预处理
while (t--) //t组数据
{
scanf("%d%d",&n,&m);
if (!m) //特判,没有移动
{
for (int i=1;i<n;i++) {putchar('1');putchar(' ');}
putchar('1'); //全部输出1
putchar(10);
continue;
}
for (int i=1;i<=n;i++)
{
k=(m/num[i]*2)+((m%num[i])/num[i-1]); //找规律
putchar(o[k%4]); //周期
if (i!=n) putchar(' ');
}
putchar(10);
}
return 0;
}