汉诺塔【模拟】

题目大意:

在正常的汉诺塔规则中再加一条:不允许直接把盘从1号柱移动到3号柱,也不允许直接把盘从3号柱移动到1号柱。初始状态为第0步,编程求在某步数时的状态。


思路:

如果把汉诺塔的变化打出来,那么就是这样的:

  1. (1,1,1) ( 1 , 1 , 1 )
  2. (2,1,1) ( 2 , 1 , 1 )
  3. (3,1,1) ( 3 , 1 , 1 )
  4. (3,2,1) ( 3 , 2 , 1 )
  5. (2,2,1) ( 2 , 2 , 1 )
  6. (1,2,1) ( 1 , 2 , 1 )
  7. (1,3,1) ( 1 , 3 , 1 )
  8. (2,3,1) ( 2 , 3 , 1 )
  9. (3,3,1) ( 3 , 3 , 1 )
  10. (3,3,2) ( 3 , 3 , 2 )
  11. (2,3,2) ( 2 , 3 , 2 )
  12. (1,3,2) ( 1 , 3 , 2 )
  13. (1,2,2) ( 1 , 2 , 2 )
  14. (2,2,2) ( 2 , 2 , 2 )
  15. (3,2,2) ( 3 , 2 , 2 )
  16. (3,1,2) ( 3 , 1 , 2 )
  17. (2,1,2) ( 2 , 1 , 2 )
  18. (1,1,2) ( 1 , 1 , 2 )
  19. (1,1,3) ( 1 , 1 , 3 )
  20. (2,1,3) ( 2 , 1 , 3 )
  21. (3,1,3) ( 3 , 1 , 3 )
  22. (3,2,3) ( 3 , 2 , 3 )
  23. (2,2,3) ( 2 , 2 , 3 )
  24. (1,2,3) ( 1 , 2 , 3 )
  25. (1,3,3) ( 1 , 3 , 3 )
  26. (2,3,3) ( 2 , 3 , 3 )
  27. (3,3,3) ( 3 , 3 , 3 )

然后,就能发现:
1号圆盘在移动3次中,共移动了2次;2号圆盘在移动9次中,共移动了2次;3号圆盘在移动27次中,共移动了2次。
那么也就很容易推出: n n 号圆盘每移动3n次中,会移动两次!
那么这道题就很好做了,预处理 3n 3 n ,每次可以利用周期问题求出答案。
时间复杂度: O(tn) O ( t n ) ,最坏 950000 950000


代码:

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当使用递归来模拟汉诺塔游戏时,需要定义一个函数来实现移动盘子的操作。下面是使用Python递归模拟汉诺塔游戏的示例代码: ```python def hanoi(n, source, target, auxiliary): if n > 0: # 将 n-1 个盘子从源柱移动到辅助柱 hanoi(n-1, source, auxiliary, target) # 将最大的盘子从源柱移动到目标柱 print(f"将盘子 {n} 从 {source} 移动到 {target}") # 将 n-1 个盘子从辅助柱移动到目标柱 hanoi(n-1, auxiliary, target, source) # 示例 n = 3 # 盘子的数量 source = "A" # 源柱 target = "C" # 目标柱 auxiliary = "B" # 辅助柱 hanoi(n, source, target, auxiliary) ``` 在上述代码中,`hanoi` 函数接受四个参数 `n`、`source`、`target` 和 `auxiliary`。其中,`n` 表示盘子的数量,`source` 表示源柱,`target` 表示目标柱,`auxiliary` 表示辅助柱。 函数内部使用递归的方式来实现汉诺塔游戏的移动操作。首先,通过递归调用 `hanoi(n-1, source, auxiliary, target)` 将 n-1 个盘子从源柱移动到辅助柱。然后,将最大的盘子从源柱移动到目标柱,并打印出移动的过程。最后,通过递归调用 `hanoi(n-1, auxiliary, target, source)` 将 n-1 个盘子从辅助柱移动到目标柱。 以上代码输出的结果为: ``` 将盘子 1 从 A 移动到 C 将盘子 2 从 A 移动到 B 将盘子 1 从 C 移动到 B 将盘子 3 从 A 移动到 C 将盘子 1 从 B 移动到 A 将盘子 2 从 B 移动到 C 将盘子 1 从 A 移动到 C ``` 这样,我们就使用递归成功模拟了汉诺塔游戏的移动过程。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值