汉诺塔

汉诺塔问题,BigInteger用法

余生颓废 提交于 2020-01-26 08:59:54
汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。 大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。 大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上(可以借助第三根柱子做缓冲)。 并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 如图【1.jpg】是现代“山寨”版的该玩具。64个圆盘太多了,所以减为7个, 金刚石和黄金都以木头代替了…但道理是相同的。 据说完成大梵天的命令需要太多的移动次数,以至被认为完成之时就是世界末日! 你的任务是精确计算出到底需要移动多少次。 很明显,如果只有2个圆盘,需要移动3次。 圆盘数为3,则需要移动7次。 那么64个呢? import java . math . BigInteger ; public class Main { public static void main ( String [ ] args ) { BigInteger bi = new BigInteger ( "2" ) ; bi = bi . pow ( 64 ) . subtract ( BigInteger . ONE ) ; System . out . println ( bi ) ; } } BigInteger用法 (此方法本题中用于计算2 64 -1,如果采用一般方法即a

python递归详解+汉诺塔小案例

旧街凉风 提交于 2020-01-25 18:09:17
递归 什么是 递归 ? 递归式方法可以被用于解决很多的计算机科学问题,因此它是计算机科学中十分重要的一个概念。绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。计算理论可以证明递归的作用可以完全取代循环,因此在很多函数编程语言(如Scheme)中习惯用递归来实现循环。递归的强大之处在于它允许用户用有限的语句描述无限的对象。因此,在计算机科学中,递归可以被用来描述无限步的运算,尽管描述运算的程序是有限的。下面是对Python递归函数的简单了解: # 类似与栈的先进后出模式 # 递归的两个必要条件 # 1.要有递推关系 # 2.要有临界 def digui(num): print('$'+str(num)) # 临界值 if num >0: # 这里用的是调用本身的函数(递推关系) digui(num-1) else: print('='*20) print(num) digui(3) 输出结果为: $3 $2 $1 $0 ==================== 0 1 2 3 汉诺塔 什么是 汉诺塔 ? 汉诺塔算法介绍 其实算法非常简单,当盘子的个数为n时,移动的次数应等于2^n – 1(有兴趣的可以自己证明试试看)。后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了。首先把三根柱子按顺序排成品字型

BZOJ 1009 [汉诺塔]

自闭症网瘾萝莉.ら 提交于 2020-01-22 00:51:48
题面 题意   对于 \(n\) 层的汉诺塔,将一个盘子从一个柱子挪到另一个柱子,这样的操作一共有六种:AB,AC,BC,BA,CA,CB,对这六种操作给出优先级,每一次从所有合法的操作中选择出上一次没有移动过的盘子中操作优先级最高的操作执行,求出需要的步数。 题解   假设空的塔底有无穷大的盘子。只考虑塔顶的盘子,每次只可能移动最小的和次小的两个盘子,而移动次小的盘子之后,次小的盘子依旧是下一时刻次小的盘子,所以最小和次小的盘子必定有一个在上一时刻被移动过,所以操作只可能是移动最小的盘子到优先级较高的堆上,以及移动次小的盘子到最大的盘子上这两个步骤的循环。   因为优先级只对最小的盘子有影响,而最小的盘子每次操作时的开始位置都确定,所以只有从同一盘子出发的操作优先级才有意义。而根据上面步骤是循环的结论,我们已经可以模拟出最小的盘子的移动轨迹。不妨令第一个塔出发到第二个塔的优先级比到第三个塔上高(如非如此,交换第二个塔和第三个塔),这样,最小的盘子的轨迹只有三种情况: \(1,2,3,1,2,3,\dots\) , \(1,2,1,2,\dots\) 和 \(1,2,3,2,3,\dots\) 。   以 \(n=4\) 为例,对于三种情况分别模拟所有盘子的移动轨迹,其中除第一列外,第 \(i\) 行第 \(j\) 列上有数字代表第 \(j\) 次操作时第 \(i\)

2020.1.7-汉诺塔算法

匆匆过客 提交于 2020-01-21 12:32:36
汉诺塔算法 汉诺塔是指,有三根棍子,在a棍子上串有从小到大依次排放的圆片,怎样移动能够使得将这些原片从a转移动c,且移动过程中始终是小圆片放在大圆片上方 def hnt(n,a,b,c): if n==1: print(‘a–c’) else: hnt(n-1,a,c,b) print(‘a-c’) hnt(n-1,b,a,c) 思想是,如果有n个圆片,n>1,那个首先要做的是把这上面的n-1个圆片从a先移动到b,然后把第n个圆片从a移动到c,再把b上的n-1个圆片从b移动到c。而把n-1个圆片从a移动到b和从b移动到c,这本身也是一个汉诺塔问题,因此可以直接调用本函数,这也就是递归思想。 我又进一步进行了思考,如果要计算出总共用的步数该怎么搞,刚开始的想法是,增加一个d=0作为默认参数,然后没进行一步,就更新d,如下代码所示: def hnt(n,a,b,c,d=0): if n==1: print(a,’–’,c) d=d+1 else: hnt(n-1,a,c,b,d) print(a,’–’,c) d=d+1 hnt(n-1,b,a,c,d) return hnt(3,a,b,c) 但是这样运行确报错了,错误的原因在于,在else这个分支之中,d返回的值还是1,加过之后的d并不能作为下一个参数去运行hnt(n-1,b,a,c,d),也就是说他不能叠加。对于递归函数而言

[ 具体数学 ] 递归式与封闭式

此生再无相见时 提交于 2020-01-20 01:46:25
递归问题 汉诺塔(HANOI) 命题 有三根杆子,第一根有大小从小到大共 \(n\) 个盘子,要求遵循以下3个规则,将在第一个杆子上全部的盘子移至第三个杆子。 每次只能移动一个盘子。 每次只能移动每个杆子最上面的盘子。 每根杆子上的盘子下面大,上面小。 求问题的最小步数。 例子: 当 \(n=3\) 时,移动方法如下图所示。 最小移动次数为 \(7\) ,故 \(n=3\) 时命题的解为 \(7\) 。 解决 方法:命名并求解 命名 设 \(H(n)\) 为 \(n\) 个盘子时汉诺塔问题的解. 三个杆子的编号分别为 \(A,B,C\) . 第 \(i\) 层盘子为 \(h_i\) . 求解 显然, \(H(1)=1\) 观察可得,将 \(n\) 个盘子从 \(A\) 移动到 \(B\) 相当于将 \(h_1,h_2\cdots h_{n-1}\) 移动至 \(B\) 后,将 \(h_n\) 移至 \(C\) ,再将 \(h_1,h_2\cdots h_{n-1}\) 移至 \(C\) . 由定义知,将 \(h_1,h_2\cdots h_{n-1}\) 从 \(A\) 移至 \(B\) 需 \(H(n-1)\) 步. \(\therefore H(n)=2H(n-1)+1\qquad H(1)=1\) 检验 已知 \(H(3)=7\) \[\because H(n)=2H(n-1

汉诺塔问题-递归

穿精又带淫゛_ 提交于 2020-01-19 21:52:58
最近看了一下递归的经典问题汉诺塔问题,并且自己用java实现了一下。 首先我们来看一下问题的描述:设 a b c 是三个塔座。开始时,在a塔上有一叠共n个圆盘,这些圆盘自上而下,由小到大的叠放在一起,个圆盘从小到大的编号为1,2,3…n,如图,现要求将塔座a上的所有圆盘都移动到塔座b上,并仍按同样的顺序叠置。在移动圆盘时应该遵循以下移动规则: 规则(1)每次只能移动一个圆盘。 规则(2)任何时刻都不允许将较大的圆盘压在较小的圆盘之上。 规则(3)在满足移动规则(1)和(2)的前提下,可将圆盘,移至a,b,c中任意一塔。 问题分析:首先将n个盘子分为两部分上层的n-1个盘子和最下层的一个最大的盘子,想要将n个盘子都移到b上,就需要先将上层的n-1个盘子都移动到c上,然后将最下层的一个盘子移动到b上,最后再将n-1个盘子从c移动到b,那么问题来了,如何把n-1个盘子从a移动到c再将从c移动到b呢,到这里仔细想我们就会发现,其实这两个问题就是和原问题相同的问题,只是问题的规模变小了1,所以说相同的问题就可以采用相同的方法,依然按照n规模的解法解决n-1的问题,这也就是递归的思想,自己调用自己,将一个规模较大的问题逐层分解,但是分解后的问题都是与原问题相同的问题,一直分解到问题可以直接解决,比如说本问题到什么时候是可以直接解决的?当然是当n=1的时候。下面就是汉诺塔问题的java实现, /

汉诺塔问题这样看,应该简单很多

◇◆丶佛笑我妖孽 提交于 2020-01-17 06:34:34
参考链接 汉诺塔问题描述 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 用递归解决问题,一个关键点是要有 递归结束 的条件 当只有一个盘子的时候,直接就是A->C,这也是递归结束的条件 当有两个盘子的时候,我们知道需要这样移动,A->B, A->C, B->C。 当有三个或三个以上的盘子的时候,我们这样来考虑把最下面的盘子当做一块,其他盘子当做一块,那么,就简化成了上一步。A柱子是源,B柱子是当做临时转换用的源,C是目的 需要注意的是,当经过上一步后,除了最下面的盘子其他的已经到了B柱子上了,这个时候,A柱子就是当做临时转换用的了,B柱子是源,C是目的。所以当n不等于1的时候,会回调两次函数,第一次参数的顺序是n,a,c,b。第二次是n,b,a,c c语言代码实现汉诺塔问题 void move(int n, char a, char b, char c) { if(n==1) { printf("%c-->%c\n", a,c); } else {//要移动第n块盘子,需要建立在n-1块的基础上 move(n-1, a, c, b);/

c语言汉诺塔

这一生的挚爱 提交于 2020-01-16 13:40:27
汉诺塔c语言 汉诺塔:汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。大梵天创造世界的时候做了三根 金刚石 柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 https://baike.baidu.com/item/%E6%B1%89%E8%AF%BA%E5%A1%94/3468295?fr=aladdin #include<stdio.h> #include<stdlib.h> int main() { int hanoi(int, char, char, char); int n, counter; printf("Input the number of diskes:"); scanf("%d", &n); printf("\n"); counter = hanoi(n, 'A', 'B', 'C'); return 0; } int hanoi(int n, char x, char y, char z) { int move(char, int, char); if (n == 1) move(x, 1, z); else { hanoi(n - 1, x, z, y); move(x, n, z); hanoi(n

python解决汉诺塔问题

梦想的初衷 提交于 2020-01-16 05:34:06
    今天刚刚在博客园安家,不知道写点什么,前两天刚刚学习完python 所以就用python写了一下汉诺塔算法,感觉还行拿出来分享一下 首先看一下描述: from : http://baike.baidu.com/link?url=fzJdDuawFsjvlLi8vjCMepByo79au3MMyu50GpMN89oj3CzEa00k5giNeuehTfQM 汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具。 大梵天 创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 传说可信但是不可全信   下面我们来看一下这个算法:    times = 0 def test(num,a,b,c): globaltimes ifnum==1: print (a,b) times+=1 else: test(num-1,a,c,b) test(1,a,b,c) test(num-1,c,b,a) test(12,"a","b","c") print "经过的步数passing:%d"%times 这里我用的是python的2.7的版本,3.X的版本可能有些不一致的地方大家注意 mun 盘子的个数 来源: https

汉诺塔(Hanoi) C#解法

核能气质少年 提交于 2020-01-13 12:53:16
上帝创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上安大小顺序摞着64片黄金圆盘。 上帝命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 有预言说,这件事完成时宇宙会在一瞬间闪电式毁灭。也有人相信婆罗门至今还在一刻不停地搬动着圆盘。 用的是递归原理 代码 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace HanoiProgram { class Program { static long count = 0 ; static void move( char x, char y) { Console.WriteLine( " {0}--->{1} " ,x,y); } static void hanoi( int n, char one, char two, char three) { if (n == 1 ) { count += 2 ; move(one, two); move(two, three); } else { count += 2 ; hanoi(n - 1 , one,two,three); move(one, two); hanoi(n