题目描述

汉诺塔问题是源于印度一个古老传说的益智玩具。大梵天创造世 界的时候做了三根金刚石柱子,在一根柱子上从上往下按照从小到小 大顺序摞着 64 片黄金圆盘。大梵天命令婆罗门把圆盘从上面开始按 从小到大顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能 放大圆盘,在三根柱子之间一次只能移动一个圆盘。 下图是圆盘个数 n=3 时的汉诺塔,这三根柱子从左向右依次编号为 A,B,C,开始 3 个圆盘都是在 A 柱上,从上往下依次编号为 1,2,3。 最后目标是把这三个圆盘都移动到 C 柱,我们知道最少移动步数是 7步。

第 1 步:1 号圆盘从 A 移动到 C

第 2 步:2 号圆盘从 A 移动到 B

第 3 步:1 号圆盘从 C 移动到 B

第 4 步:3 号圆盘从 A 移动到 C

第 5 步:1 号圆盘从 B 移动到 A

第 6 步:2 号圆盘从 B 移动到 C

第 7 步:1 号圆盘从 A 移动到 C 更一般的,如果是 n 个圆盘,最少移动步数是 2^n2
n
-1。 现在你的任务是:告诉你圆盘数 n(这些盘初始都在 A 柱上,而且从上往下编号 1 到 n),问你把这 n 个圆盘移动到 C 柱上,在最少步数移动过程中第 x 步移动的圆盘的编号,以及它从哪个柱子移动到哪个柱子?

输入

总共两行,第一行 1 个整数 n。 第二行 1 个整数 x。

输出

总共两行,第一行 1 个整数,表示第 x 步移动圆盘的编号。 第二行两个字母,中间有一个空格,表示第 x 步是从第一个字母的柱字移到第二个字母的柱子

样例

样例1
输入

3
6

输出

2
B C

样例2
输入

45 12345678910

输出

2
C A

提示
对于 20%的数据:1≤n≤16; 对于 50%的数据:1≤n≤32; 对于 100%的数据:1≤n≤64,1≤x≤2^n -1

题解

这道题先看数据量就知道肯定要用高精度,并且不能用普通方法,要找规律(至于为什么这样说后面我会说的)

朴素方法

#include<bits/stdc++.h>
using namespace std;
long long n,m,sum=0;
char a,b,c;
void f(int n,char a,char c,char b)
{if(n>0){f(n-1,a,b,c);sum++;if(sum==m){printf("%d\n",n);printf("%c %c",a,c);}f(n-1,b,c,a);}
}
int main()
{cin>>n;cin>>m;a='A';b='B';c='C';f(n,a,c,b);
}

long long的长度为2^32-1 跟题目的2^64-1相差甚远,所以内存就会炸。因为它是递归,又因为数据量太大所以还会超时

AC方法

既然要找规律,那么我们就先写一个打表的代码

#include<bits/stdc++.h>
#include<windows.h>
using namespace std;
long long n,sum=0;
char a,b,c;
void f(long long n,char a,char c,char b)
{if(n>0){f(n-1,a,b,c);sum++;cout<<"第"<<sum<<"步"<<" "<<n<<"  "<<a<<c<<"    ";if(sum%3==0){cout<<endl;}f(n-1,b,c,a);}
}
int main()
{cin>>n;a='A';b='B';c='C';f(n,a,c,b);
}

以下为打表出来的结果


由这两幅图我们不难发现数字与字母的规律

数字规律

#include<bits/stdc++.h>
using namespace std;
int main()
{long long n,m;cin>>n>>m;if(m%2==1)cout<<1<<endl;else{long long k=1;long long p=m;while(p%2==0&&p!=0){p/=2;k++;}cout<<k<<endl;}return 0;}

这里并没有用高精度,在源代码上会说明

字母规律

if(n%2==0){if(check1(3)==0){if(temp%2==0){cout<<"C B";return 0;}else{cout<<"B C";return 0;}}elseif(check1(3)==1){if(temp%2==0){cout<<"B A";return 0;}else{cout<<"A B";return 0;}}elseif(check1(3)==2){if(temp%2==0){cout<<"A C";return 0;}else{cout<<"C A";return 0;}}}else{if(check1(3)==0){if(temp%2==0){cout<<"B C";return 0;}else{cout<<"C B";return 0;}}elseif(check1(3)==1){if(temp%2==0){cout<<"C A";return 0;}else{cout<<"A C";return 0;}}elseif(check1(3)==2){if(temp%2==0){cout<<"A B";return 0;}else{cout<<"B A";return 0;}}}

n为圆盘数量,temp储存的是当前移动圆盘的编号,check1为高精度取余函数

有了上述的规律那么我们就可以完成这道题目了

#include<bits/stdc++.h>
using namespace std;
int n,m=0,k=1,num=1;//k为当前移动圆盘的编号
char a[22],e[22];
int b[22],c[22];
long long check(int n)//这里为一个特殊的高精度取余
{long long ans=0;for(int i=num;i<=m;i++)ans=(ans*10+(a[i]-'0'))%n;return ans;
}
long long check1(int x)//普通的高精度取余
{long long sum=0;for(int i=1;i<=m;i++)sum=(sum*10+(e[i]-'0'))%x;return sum;
}
int main()
{cin>>n;while(cin>>a[++m]);//为防止步数为高精度数所以用char数组输入 m--;//为数组的长度 for(int i=1;i<=m;i++)//将数据转换成int形(下面有用) b[i]=a[i]-'0';for(int i=1;i<=m;i++)//用e[i]备份一下 e[i]=a[i];//数字规律 if(a[m]=='1'||a[m]=='3'||a[m]=='5'||a[m]=='7'||a[m]=='9')//由上面的找到的规律可以得到 cout<<1<<endl;else{while(check(2)==0)//根据规律这里的数字要不断变化,所以专门要写一个高精度取余 {//高精度除法 long long f=0;for(int i=num;i<=m;i++){c[i]=(f*10+b[i])/2;f=(f*10+b[i])%2;}long long len=num;while(c[len]==0&&len<m)len++;num=len;//因为数字是不断变化的,所以数组的数要不断后移,因此要用num来储存len for(int i=len;i<=m;i++){a[i]=c[i]+'0';b[i]=c[i];}k++;}cout<<k<<endl;}//字母规律 if(n%2==0){if(check1(3)==0){if(k%2==0){cout<<"C B";return 0;}else{cout<<"B C";return 0;}}elseif(check1(3)==1){if(k%2==0){cout<<"B A";return 0;}else{cout<<"A B";return 0;}}elseif(check1(3)==2){if(k%2==0){cout<<"A C";return 0;}else{cout<<"C A";return 0;}}}else{if(check1(3)==0){if(k%2==0){cout<<"B C";return 0;}else{cout<<"C B";return 0;}}elseif(check1(3)==1){if(k%2==0){cout<<"C A";return 0;}else{cout<<"A C";return 0;}}elseif(check1(3)==2){if(k%2==0){cout<<"A B";return 0;}else{cout<<"B A";return 0;}}}
}

2022苏州市小学信息学奥赛T2-汉诺塔相关推荐

  1. java三个柱子汉诺塔问题

    题目 移动盘子,每一次只能移动一个,小盘子在大盘子上. 打印1 from A to B过程 注意 1)盘子编号的变化和辅助柱子的变化 2)当盘子编号为1时,结束递归,此时移动结束 代码 package ...

  2. 信息学奥赛一本通 1205:汉诺塔问题 | OpenJudge 2.2 6261:汉诺塔问题

    [题目链接] [ybt 1205:汉诺塔问题 OpenJudge 2.2 6261:汉诺塔问题 [题目考点] 1. 递归 [解题思路] 设输入的左中右三个杆分别为a,b,c.题目要将摞在a杆上的n层汉 ...

  3. 信息学奥赛一本通(1205:汉诺塔问题)

    1205:汉诺塔问题 时间限制: 1000 ms         内存限制: 65536 KB 提交数: 19568     通过数: 7240 [题目描述] 约19世纪末,在欧州的商店中出售一种智力 ...

  4. 汉诺塔问题(信息学奥赛一本通-T1205)

    [题目描述] 约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下.由小到大顺序串着由64个圆盘构成的塔.目的是将最左边杆上的盘全部移到中间的杆上,条件是一次只能移 ...

  5. 2022蓝桥模拟-子汉诺塔

    问题描述 小蓝很喜欢玩汉诺塔游戏. 游戏中有三根柱子,开始时第一根柱子上有 n 个圆盘,从上到下圆盘的大小依次为 1 到 n. 每次,可以将一个盘子从一根柱子上移动到另一根柱子上,这个盘子必须是柱子最 ...

  6. Tower of Hanoi(汉诺塔)详解

    一个经典的汉诺塔问题,带着我自己的理解给做这个问题的友友们解决一下,包括我本人在做的时候也遇到的一些问题给大家阐述一下.话不多说,来看: 汉诺塔 问题描述: 汉诺塔(Hanoi Tower),又称河内 ...

  7. 汉诺塔细讲(内含邻近,循环。以及作者对汉诺塔,以及分治算法的小感悟,注释)

    小伙伴们大家好,今天是我第一次尝试去发文写作,有不好之处请多多包含. 什么是汉诺塔呢? 其实大家已经很熟悉他了(而且这是我的第一个递归题目) 注意:本章统一是将从第一根柱子转移到第三根柱子 汉诺塔(T ...

  8. 代码记录丨小青蛙和汉诺塔

    我好菜哦. btw原来CSDN这里这么方便!!太好了(o^u^o) (这个平台最好能供我乱搞!(大言不惭 青蛙跳台阶: #include <stdio.h>//青蛙跳台阶 //(笑死我了我 ...

  9. 汉诺塔和小青蛙跳台阶问题

    //Editor:ApophisJ //Date:2022年10月12日 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> //汉诺 ...

  10. python turtle绘图-案例集锦(小猪佩奇、哆啦A梦、小黄人、樱花树、皮卡丘、汉诺塔、高达、星空等)

    1.小猪佩奇: import turtle as t t.pensize(4) t.hideturtle() t.colormode(255) t.color((255, 155, 192), &qu ...

最新文章

  1. 佛弟子有三样东西需要永远保密!
  2. ThinkPHP第二十三天(Category表结构、PHPExcel导入数据函数)
  3. [转]【Git】rebase 用法小结
  4. Java虚拟机垃圾收集器初步学习
  5. 7.MATLAB变量——矩阵操作二
  6. 杭电1043java实现bfs一遍
  7. formcheck 自定义验证
  8. Java命令行界面(第3部分):jbock
  9. 区块链组织架构_区块链可以加速开放组织的5种方式
  10. linux ls 时间显示时间格式,ls -l显示的日期格式如何设定?
  11. Leetcode | Pow(x, n)
  12. C# 多线程处理 I(转载)
  13. Verilog实现的格雷码与二进制码的互相转换
  14. 【Opencv实战】这是我见过的最强大“美颜滤镜”,代码美颜傻瓜式一键操作~(附源码)
  15. Cannot use the diamond generic notation when running in JDK inferior to 1.7 mode
  16. VIJOS-P1625 精卫填海(背包)
  17. 刘强东,一个农村孩子的自卑!
  18. C盘清理方法——基于spacesniffer软件和PatchCleaner软件
  19. 你有多久没有收到圣诞节的祝福了,你收到那个女孩(男孩)的祝福了吗?
  20. ROS常用的仿真软件

热门文章

  1. java版 高斯过程,三维高斯过程回归
  2. JAVA集成华为推送 服务端
  3. led灯条串联图_10个LED灯并联再串联
  4. wget无法批量下载气象数据的解决方案(Python、迅雷批量下载气象数据方法)
  5. 关于防范ONION勒索软件病毒攻击的解决办法
  6. 提示获取硬盘分区失败,可能缺少硬盘驱动(ThinkStation使用U启动重装系统)
  7. adprw指令通讯案例_S71200 ModbusTCP 通讯配置向导说明
  8. 集成算法 | 随机森林回归模型
  9. Word使用中常用的快捷键
  10. MICIN、LINEIN、LINEOUT、HPOUT、麦克风、耳机、扬声器一次说明白