汉诺塔

递归函数-汉诺塔经典递归

非 Y 不嫁゛ 提交于 2020-02-25 01:15:06
前言 最近在读《JavaScript语言精粹》,对递归函数有了进一步的认识,希望总结下来: 递归是一种强大的编程技术,他把一个问题分解为一组相似的子问题,每一问题都用一个寻常解去解决。递归函数就是会直接或者间接调用自身的一种函数,一般来说,一个递归函数调用自身去解决它的子问题。 "汉诺塔"经典递归问题 "汉诺塔"是印度的一个古老传说,也是程序设计中的经典的递归问题,是一个著名的益智游戏:   题目如下:     塔上有三根柱子和一套直径各不相同的空心圆盘,开始时源柱子上的所有圆盘都按从大到小的顺序排列。目标是通过每一次移动一个圆盘到另一根柱子上,最终把一堆圆盘移动到目标柱子上,过程中不允许把较大的圆盘放置在较小的圆盘上;      寻找规律(把所有的圆盘移动到C):   1)n(圆盘个数) == 1     第一次:1号盘 A -> C sum(移动次数) = 1   2)n == 2     第一次:1号盘 A -> B     第二次:2号盘 A -> C     第三次:1号盘 B -> C  sum = 3   3)n == 3     第一次:1号盘 A -> C     第二次:2号盘 A -> B     第三次:1号盘 C -> B     第四次:3号盘 A -> C     第五次:1号盘 B -> A     第六次:2号盘 B -> C     第七次

Hanoi Tower 汉诺塔问题

﹥>﹥吖頭↗ 提交于 2020-02-25 01:14:36
Hanoi Tower 汉诺塔问题 汉诺(Hanoi)塔问题:古代有一个梵塔,塔内有三个座A、B、C,A座上有64个盘子,盘子大小不等,大的在下,小的在上(如图)。有一个和尚想把这64个盘子从A座移到B座,但每次只能允许移动一个盘子,并且在移动过程中,3个座上的盘子始终保持大盘在下,小盘在上。在移动过程中可以利用B座,要求打印移动的步骤。 其实算法非常简单,当盘子的个数为n时,移动的次数应等于2^n – 1(有兴趣的可以自己证明试试看)。后来一位美国学者发现一种出人意料的简单方法,只要轮流进行两步操作就可以了。首先把三根柱子按顺序排成品字型,把所有的圆盘按从大到小的顺序放在柱子A上,根据圆盘的数量确定柱子的排放顺序:若n为偶数,按顺时针方向依次摆放 A B C; 若n为奇数,按顺时针方向依次摆放 A C B。 (1)按顺时针方向把圆盘1从现在的柱子移动到下一根柱子,即当n为偶数时,若圆盘1在柱子A,则把它移动到B;若圆盘1在柱子B,则把它移动到C;若圆盘1在柱子C,则把它移动到A。 (2)接着,把另外两根柱子上可以移动的圆盘移动到新的柱子上。即把非空柱子上的圆盘移动到空柱子上,当两根柱子都非空时,移动较小的圆盘。这一步没有明确规定移动哪个圆盘,你可能以为会有多种可能性,其实不然,可实施的行动是唯一的。 (3)反复进行(1)(2)操作,最后就能按规定完成汉诺塔的移动。

汉诺塔问题(Hanoi)

北慕城南 提交于 2020-02-22 06:18:28
描述 一、汉诺塔问题 有三根杆子A,B,C。A杆上有N个(N>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至C杆: 每次只能移动一个圆盘; 大盘不能叠在小盘上面。 提示:可将圆盘临时置于B杆,也可将从A杆移出的圆盘重新移回A杆,但都必须遵循上述两条规则。 问:如何移?最少要移动多少次? 汉诺塔示意图如下: 三个盘的移动: 二、故事由来 法国数学家爱德华·卢卡斯曾编写过一个印度的古老传说:在世界中心贝拿勒斯(在印度北部)的圣庙里,一块黄铜板上插着三根宝石针。印度教的主神梵天在创造世界的时候,在其中一根针上从下到上地穿好了由大到小的64片金片,这就是所谓的汉诺塔。不论白天黑夜,总有一个僧侣在按照下面的法则移动这些金片:一次只移动一片,不管在哪根针上,小片必须在大片上面。僧侣们预言,当所有的金片都从梵天穿好的那根针上移到另外一根针上时,世界就将在一声霹雳中消灭,而梵塔、庙宇和众生也都将同归于尽。 不管这个传说的可信度有多大,如果考虑一下把64片金片,由一根针上移到另一根针上,并且始终保持上小下大的顺序。这需要多少次移动呢?这里需要 递归 的方法。假设有n片,移动次数是f(n).显然f(1)=1,f(2)=3,f(3)=7,且f(k+1)=2*f(k)+1。此后不难证明f(n)=2^n-1。n=64时, 假如每秒钟一次,共需多长时间呢

KO递归之汉诺塔---C语言

馋奶兔 提交于 2020-02-19 04:13:31
汉诺塔: 汉诺塔(Tower of Hanoi)源于印度传说中,大梵天创造世界时造了三根金钢石柱子,其中一根柱子自底向上叠着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 单看这个问题描述有点让人抓瞎,这是当然,无论多么简单的问题描述,在没有建立具体地模型之前都是让人不知所云的,仅仅用生活中的语言去描述一些数学或算法问题往往会让听者产生理解偏差, 这也和每个的理解能力和思维方式有很大关系,这就显示出数学的强大了,数学让问题不再模糊,参数和公式组成的模型让问题不再有理解偏差和误区,只可惜数学没学好,看来以后还得回来把高数、概率论这些给补回来。 说了一些题外话,下面来对汉诺塔问题进行解释和建立模型 这是示意图,a是起始柱,c是目标柱,b起到中转作用 在进行转移操作时,都必须确保大盘在小盘下面,且每次只能移动一个圆盘,最终c柱上有所有的盘子且也是从上到下按从小到大的顺序。 很多时候看到这些蛋疼和矫情操作就觉得数学家真是思维清奇、智慧如海,嗯还有吃饱了撑的,某兄台邪魅地一笑,道:直接把c和a交换位置不就行了,我想这位兄台以后或成大器或被人打死。 问题看起来并不复杂,当a柱子上只有一个盘子时只要把那个盘子直接移到c就行了, 有两个盘子的话把1号盘先移到b柱,在把2号盘移到c柱

牛客 汉诺塔(LIS、Dilworth定理)

旧城冷巷雨未停 提交于 2020-02-16 22:54:41
题目链接: 点击这里 纠结了一上午,晚上才瞥到这个条件“ Xi 互不相等且 Yi 互不相等 ” T^T 将木板按照 Xi 从小到大排序,将这时的 Yi 记为 Zi 数列,则问题变成将 Zi 划分为尽可能少的若干组上升子序列,即求最长上升子序列的个数。 根据Dilworth定理,最长上升子序列的个数等于最长不上升子序列的长度。 借助 O ( n l o n g n ) O(nlongn) O ( n l o n g n ) 的算法,在求出最小组数的同时得出分组方案。 # include <iostream> # include <algorithm> # include <string> # include <cstdio> # include <cstring> # include <cmath> # include <stack> # include <queue> # include <map> # include <set> using namespace std ; typedef long long ll ; const int MOD = 10000007 ; const int INF = 0x3f3f3f3f ; const double PI = acos ( - 1.0 ) ; const int maxn = 100010 ; struct node {

《汉诺塔》进阶内容算法

夙愿已清 提交于 2020-02-13 22:03:45
哈喽,大家好,我是Tony: 欢迎大家访问我的个人主页: Tony’s Blog ,让我们一起站在巨人的肩膀之上! 这篇博客将以《汉诺塔》为基础进行汉诺塔进阶: 编程题 给定一个整形数组arr,其中只含有1,2和3,代表所有圆盘目前的状态,1代表左柱,2代表中柱,3代表右柱,arr[i]的值代表第i+1个圆盘的位置。比如,arr=[3,3,2,1],代表第一个圆盘在右柱上、第2个圆盘在右柱上、第3个圆盘在中柱、第4个圆盘在左柱上。如果arr代表的状态是最优移动轨迹过程中出现的状态,返回arr这种状态是最优移动轨迹中的第几个状态。如果arr代表的状态不是最优移动轨迹过程中出现的状态,则返回-1. 举例 arr[1,1]。两个圆盘目前都在左柱上,也就是初始状态,所以返回0. arr[2,1]。第一个圆盘在中柱上,第二个圆盘在左柱上,这个状态是2个圆盘的汉若塔游戏最优移动轨迹的第1步,所以返回1 arr[3,3]。第一个圆盘在右柱上,第2个圆盘在右柱山个,这个状态是2个圆盘的汉诺塔游戏中最优移动轨迹的第3步,所以返回3. arr[2,2]。第一个圆盘在中柱上、第二个圆盘在中柱上,这个状态是2个圆盘的汉若塔游戏最优移动轨迹中不会出现的状态,所以返回-1. 说明 汉诺塔永远只有三步: 把n-1的盘子移动到缓冲区 把1号从起点移到终点 把缓冲区的n-1号盘子移动到终点 因此算法是找到 最大圆盘

从《汉诺塔》来讲递归算法

元气小坏坏 提交于 2020-02-12 23:01:35
哈喽,大家好,我是Tony: 这篇博客将以《汉诺塔》为例进行递归编程: 编程题 给定一个整数n,代表汉诺塔游戏中从小到大放置的n个圆盘,假设开始时所有的圆盘都放到左边的桌子上,想按照汉诺塔游戏规则把所有的圆盘都移到右边的柱子上。实现函数打印最优移动轨迹 举例 n=1时,打印: move from left to right n=2时,打印: move from left to mid move from left to right move from mid to right 说明 这是一个典型的汉若塔问题,汉若塔问题永远都是经典的三步走: 把n-1的盘子移动到缓冲区 把1号从起点移到终点 把缓冲区的n-1号盘子移动到终点 代码(C++): // ConsoleApplication2.cpp : 定义控制台应用程序的入口点。 //汉诺塔问题 #include "stdafx.h" #include<iostream> #include<vector> #include<string> using namespace std; void funoi2(int n, string from, string buffer, string to) { if (n==1) { cout <<"Move "<<"from "<<from<<" "<< "to "<<to<<endl; }

汉诺塔

柔情痞子 提交于 2020-02-12 22:51:02
汉诺塔 先带大家了解一下汉诺塔。 相传在 古印度 圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置64个金盘。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上。 例:先用三个盘子分析一下解题思路—— 1、先是给A柱上放三个盘子,标号为1(顶层)、2(中层)、3(底层),刚好符合从大到小; 2、再把1和2看成一个整体,因此A柱上的盘子就有两个,(1,2)(顶层)、3(底层); 3、先把(1,2)盘移到B柱上,再把3移到C柱上; 4、这下把(1,2)又分开,就成了1、2,并且都在B柱上,现在又把1移到A柱上; 5、再把2移到C柱上,再把最后一个盘子1移到C柱上,目标达成。 如果为64个盘子————先把前面63个看成一个整体,64因此就被分为两个部分,接着把63又分为两个部分,前62个盘子和63, 以此类推。具体实现步骤如下: import java.util.Scanner; /* 汉诺塔————要求:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。 操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下, 小盘在上

汉诺塔问题(C++)

此生再无相见时 提交于 2020-02-12 14:22:42
模拟盘子移动过程,以三个盘子为例 第一次:最小盘到C 中间盘到到B 最小盘到B 最大盘到C 最小盘到A 中盘到c 小盘到c 实现这个算法可以简单分为三个步骤: (1) 把n-1个盘子由A 移到 B;(C为过渡盘) (2) 把第n个盘子由 A移到 C; (3) 把n-1个盘子由B 移到 C;(A为过渡盘) 到目前为止,求解汉诺塔问题最简单的算法还是同过递归来求,我们说的简单点就是自己是一个方法或者说是函数,但是在自己这个函数里有调用自己这个函数的语句,必须有一个结束点,或者具体的说是在调用到某一次后函数能返回一个确定的值,接着倒数第二个就能返回一个确定的值,一直到第一次调用的这个函数能返回一个确定的值。 代码: #include "stdafx.h" #include <iostream> using namespace std; void hannuota(int n,char src,char medium,char dest); int _tmain(int argc, _TCHAR* argv[]) { int m; cout<<"请输入盘子数量:"; cin>>m; cout<<"移动"<<m<<"个盘子:"<<endl; hannuota(m,'A','B','C'); system("pause"); return 0; } void move(char src

汉诺塔(记录每种路径次数)

一世执手 提交于 2020-02-11 02:24:45
https://ac.nowcoder.com/acm/contest/3004/I 题意:输出汉诺塔移动过程中每一种移动的次数和移动总数。 如下 A->B:XX A->C:XX B->A:XX B->C:XX C->A:XX C->B:XX SUM:XX 解法:记忆化搜索,当前状态的可以由上一状态得到。 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <iostream> #include <cstdio> #include <string> #include <stdio.h> #include <queue> #include <stack> #include <map> #include <set> #include <string.h> #include <vector> #define ME(x , y) memset(x , y , sizeof(x)) #define SF(n) scanf("%d" , &n) #define rep(i , n) for(int i = 0 ; i < n ; i ++) #define INF 0x3f3f3f3f #define mod 998244353 #define PI acos(-1) using