Hanoi双塔问题 代码加注释
Hanoi塔问题Hanoi塔问题...
PARTITION过程
以 2 8 7 1 以 6 10 13 5 3 8 5 3 6 2 4 为例 11为例
PARTITION(A, p, r) x←A[r] i←p-1 for j ← p to r-1 do if A[j] ≤ x then i ← i+ 1 exchange A[i] ↔A[j] exchange A[i+1] ↔A[r] return i+1
10
递归举例-汉诺(Hanoi)塔问题
汉诺(Hanoi)塔问题分析
n=1时,直接a->b即可 n>1时,借助c实现移动,可先将n-1个圆盘按照规 则a->c,再将大圆盘a->b,最后将n-1个圆盘c->b 可以通过递归实现
伪码: hanoi(int n,int a,int b,int c) { if(n>0){hanoi(n-1,a,c,b); move(a,b); hanoi(n-1,c,b,a)} }
logb a −
b b b
logb a
)
19
主方法的应用
请注意,上述三种情况没有覆盖所有的f(n) 在应用时需要注意是否符合这三种情况 T(n) = 4T(n/2) + n T(n) = 4T(n/2) + n2 T(n) = 4T(n/2) + n3 T(n) = 4T(n/2) + n2/lgn T(n) = 2T(n/2) + nlgn
20
分治法
分治法的基本策略
分解(Divide):将原问题分解为子问题 解决(Conquer):求解子问题 合并(Combine):组合子问题的解得到原问题的 解
21
分治法的适用条件
java汉诺塔详解及实现代码
java汉诺塔详解及实现代码java 汉诺塔详解及实现代码实现效果图打印的⽅法在 moveTheTopOne() ⽅法中被调⽤,调⽤该⽅法前打印出移动的⽅向--从X号塔往Y号塔汉诺塔要求:将第⼀座塔上的所有盘⼦,借助第⼆座塔,全部搬运到第三座塔上。
规则:⼀次只能搬运⼀个盘⼦,不准将⼤盘⼦落在⼩盘⼦上。
汉诺塔实现代码:public class NewHanoi {public static int tiers = 4; // tiers 层数private static List<String> pagoda1 = new ArrayList<String>(); // 静态指针private static List<String> pagoda2 = new ArrayList<String>();private static List<String> pagoda3 = new ArrayList<String>();// 映射,⽤来确定并打印塔的序号(使⽤⾓标),也可以使⽤ Mapprivate static List[] mapping = {pagoda1, pagoda2, pagoda3};public static void main(String[] args) {preparePagoda(pagoda1, tiers);System.out.println("初始状态:");printPagodas();hanoi(tiers, pagoda1, pagoda2, pagoda3);System.out.println("最后结果:");printPagodas();}// --准备盘⼦(添加-字符串) (源塔)上private static void preparePagoda(List<String> srcPagoda, int tiers) {// ⽤于拼装塔层的容器StringBuilder builder = new StringBuilder();// 源塔的每⼀层加盘⼦,从底层开始, i ‘代表'盘⼦的直径⼤⼩,等于组成盘⼦的"^"个数for(int i = tiers; i > 0; i--){// 每⼀层由 2*tiers-1 个格⼦组成,代表盘⼦⼤⼩的"^"格⼦由空格隔开for(int k = 0; k < tiers - i; k++) builder.append(" "); // 盘⼦左边的空格,数量为 [2*tiers-1-(2*i-1)]/2 = tiers-i, 右边相同 for(int j = 1; j <= 2*i-1; j++){ // 盘⼦所占格数if(j % 2 == 1) builder.append("^"); // 间隔摆放else builder.append(" ");}for(int k = 0; k < tiers - i; k++) builder.append(" "); // 盘⼦右边的空格srcPagoda.add(builder.toString()); // 添加到塔上builder.delete(0, builder.length()); // 下⼀循环前清空容器}}// --打印塔的现状private static void printPagodas(){// 打印层数为三座塔-现状的最⼤⾼度int len = Math.max(pagoda1.size(), Math.max(pagoda2.size(), pagoda3.size()));// ⽤于-塔的空层显⽰StringBuilder spaces = new StringBuilder();spaces.append("-"); // --添加塔的左外框for(int i = 0; i < 2*tiers-1; i++) spaces.append(" "); // 空层显⽰⽤空格spaces.append("-\t"); // --添加塔的右外框和塔间间隔for(int i = len - 1; i >= 0; i--){ // 从顶层开始// 三座塔同⼀⽔平⾯的塔层放在同⼀⾏显⽰// 当某个塔不存在此层时,List.get(index)会抛⾓标越界异常,使⽤try-catch处理:此层显⽰⼀层空格try { System.out.print("-" + pagoda1.get(i) + "-\t");} catch (Exception e1) { System.out.print(spaces);}try { System.out.print("-" + pagoda2.get(i) + "-\t");} catch (Exception e) { System.out.print(spaces);}try { System.out.print("-" + pagoda3.get(i) + "-\t");} catch (Exception e) { System.out.print(spaces);}System.out.print("\r\n");}}// 这个⽅法(递归的核⼼⽅法)从指定的源塔上移动-指定数量的盘⼦-到指定的⽬标塔上public static void hanoi(int moveNum, List<String> from, List<String> middle, List<String> to) {if(moveNum == 1){ // 递归到移动⼀个盘⼦时,使⽤ move ⽅法moveTheTopOne(from, to);return;}// 将实现分为三步,⼀,将源塔底盘上⽅的所有盘⼦移⾄中间塔(递归);⼆,将底盘移到⽬标塔;三,将中间塔上的所有盘⼦移到⽬标塔上(递归)。
高精度运算文档
1.Hanoi双塔问题(hanoi.pas)-noip07-4【问题描述】给定A、B、C三根足够长的细柱,在A柱上放有2n个中间有孔的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形)。
现要将这些圆盘移到C柱上,在移动过程中可放在B柱上暂存。
要求:(1)每次只能移动一个圆盘;(2)A、B、C三根细柱上的圆盘都要保持上小下大的顺序;任务:设A n为2n个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出A n。
【输入】输入文件hanoi.in为一个正整数n,表示在A柱上放有2n个圆盘。
【输出】输出文件hanoi.out仅一行,包含一个正整数, 为完成上述任务所需的最少移动次数A n。
【限制】对于50%的数据,1<=n<=25对于100%的数据,1<=n<=200【提示】设法建立A n与A n-1的递推关系式。
2.麦森数(Mason.pas)-noip2003-4【问题描述】形如2P-1的素数称为麦森数,这时P一定也是个素数。
但反过来不一定,即如果P是个素数,2P-1不一定也是素数。
到1998年底,人们已找到了37个麦森数。
最大的一个是P=3021377,它有909526位。
麦森数有许多重要应用,它与完全数密切相关。
任务:从文件中输入P(1000<P<3100000),计算2P-1的位数和最后500位数字(用十进制高精度数表示)【输入格式】文件中只包含一个整数P(1000<P<3100000)【输出格式】第一行:十进制高精度数2P-1的位数。
第2-11行:十进制高精度数2P-1的最后500位数字。
(每行输出50位,共输出10行,不足500位时高位补0)不必验证2P-1与P是否为素数。
【输入样例】1279【输出样例】386000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104079321946643990819252403273640855386152622472667048053191123504036080596733602980122394417323241848424216139542810077913835662483234649081399066056773207629241295093892203457731833496615835504729594205476898112116936771475484788669625013844382602917323488853111608285384165850282556046662248318909188018470682222031405210266984354887329580288780508697361869007147207105557031687290873.循环(circle.pas)-noip05-4【问题描述】乐乐是一个聪明而又勤奋好学的孩子。
汉诺塔python代码
汉诺塔python代码汉诺塔游戏是一种经典的益智游戏,它的规则非常简单,但是解决这个问题却需要一定的思维能力,而且它还可以通过编程来实现。
Python是一门非常流行的编程语言,因此在这里我们将介绍如何使用Python来实现汉诺塔游戏。
一、汉诺塔游戏的规则汉诺塔游戏有三个柱子和若干个盘子,每个盘子大小不同。
开始时,所有盘子都放在一个柱子上,按照从大到小的顺序排列。
目标是将所有盘子从起始柱子移动到目标柱子上,并保持原来的顺序不变。
在移动过程中必须遵守以下规则:1. 每次只能移动一个盘子;2. 盘子只能放在比它大的盘子上面;3. 不能将一个大盘子放在一个小盘子上面。
二、使用递归算法实现汉诺塔游戏递归算法是解决汉诺塔问题最常用的方法之一。
下面我们将介绍如何使用递归算法来实现汉诺塔游戏。
1. 定义函数首先我们需要定义一个函数来实现汉诺塔游戏。
在这个函数中,我们需要传入三个参数:起始柱子、目标柱子和盘子的数量。
def hanoi(start, target, n):2. 判断递归结束条件在递归过程中,我们需要判断递归结束的条件。
当n等于1时,表示只有一个盘子需要移动,此时我们可以直接将它从起始柱子移动到目标柱子上。
if n == 1:print(start, "->", target)3. 递归调用如果n大于1,则需要进行递归调用。
首先我们需要将n-1个盘子从起始柱子移动到辅助柱子上,然后再将最后一个盘子从起始柱子移动到目标柱子上,最后将n-1个盘子从辅助柱子移动到目标柱子上。
else:hanoi(start, other, n-1)print(start, "->", target)hanoi(other, target, n-1)4. 完整代码下面是完整的使用递归算法实现汉诺塔游戏的Python代码:def hanoi(start, target, n):if n == 1:print(start, "->", target)else:other = 6 - start - targethanoi(start, other, n-1)print(start, "->", target)hanoi(other, target, n-1)hanoi(1, 3, 3)三、使用非递归算法实现汉诺塔游戏除了递归算法,我们还可以使用非递归算法来实现汉诺塔游戏。
汉诺塔递归算法及详解
汉诺塔递归算法及详解汉诺塔(Hanoi Tower)是一种数学谜题,由法国数学家Édouard Lucas在19世纪中期提出。
这个谜题由三根柱子和一组圆盘组成,圆盘从上到下按照从小到大的顺序放置在柱子上。
问题的目标是将所有圆盘从一个柱子移动到另一个柱子,每次只能移动一个圆盘,并且不能将大的圆盘放在小的圆盘上面。
解决汉诺塔问题的一种常见方法是使用递归算法。
递归是一种数学和计算机科学中常见的方法,通过将复杂的问题分解为更小的相同问题的子问题来解决。
汉诺塔的递归算法主要包含以下步骤:1.将N-1个圆盘从起始柱子移动到中间柱子上,这可以通过将起始柱子作为源柱子,中间柱子作为辅助柱子,目标柱子为空柱子来实现。
这个步骤可以通过递归调用来实现,将起始柱子作为源柱子,中间柱子作为辅助柱子,目标柱子作为空柱子。
2.将第N个圆盘从起始柱子移动到目标柱子上。
3.将N-1个圆盘从中间柱子移动到目标柱子上,这可以通过将中间柱子作为源柱子,目标柱子作为辅助柱子,起始柱子作为空柱子来实现。
这个步骤可以通过递归调用来实现,将中间柱子作为源柱子,目标柱子作为辅助柱子,起始柱子作为空柱子。
下面是一个示例代码,使用递归算法解决汉诺塔问题:```pythondef hanoi(n, source, target, auxiliary):if n > 0:#将N-1个圆盘从起始柱子移动到中间柱子hanoi(n-1, source, auxiliary, target)#将第N个圆盘从起始柱子移动到目标柱子print("Move disk", n, "from", source, "to", target)#将N-1个圆盘从中间柱子移动到目标柱子hanoi(n-1, auxiliary, target, source)#测试n=3hanoi(n, 'A', 'C', 'B')```上述代码中,`hanoi(`函数接受四个参数:圆盘的数量n,起始柱子source,目标柱子target和辅助柱子auxiliary。
汉诺塔java代码
汉诺塔java代码汉诺塔(Hanoi Tower)是经典的递归问题,它涉及到将一组圆盘从一个垂直柱子移动到另一个垂直柱子,中间通过第三个柱子。
这个问题可以通过递归的方式非常优雅地解决。
下面是使用Java编写的汉诺塔问题的代码,代码注释详细解释了每个步骤的含义。
```java/*** 汉诺塔问题的Java实现*/public class HanoiTower {/*** 汉诺塔问题的解决方法** @param n 圆盘的数量* @param from 起始柱子* @param to 目标柱子* @param aux 辅助柱子*/public static void solveHanoi(int n, char from, char to, char aux) {// 如果只有一个圆盘,直接移动到目标柱子if (n == 1) {System.out.println("移动圆盘 1 从柱子 " + from + " 到柱子 " + to);return;}// 将 n-1 个圆盘从起始柱子移动到辅助柱子,目标柱子作为辅助solveHanoi(n - 1, from, aux, to);// 移动第 n 个圆盘到目标柱子System.out.println("移动圆盘 " + n + " 从柱子 " + from + " 到柱子 " + to);// 将 n-1 个圆盘从辅助柱子移动到目标柱子,起始柱子作为辅助solveHanoi(n - 1, aux, to, from);}public static void main(String[] args) {// 圆盘的数量int numberOfDiscs = 3;// 调用解决方法solveHanoi(numberOfDiscs, 'A', 'C', 'B');}}```在这段Java代码中,我们使用了一个递归函数`solveHanoi`来解决汉诺塔问题。
hanoi塔递归算法
hanoi塔递归算法Hanoi塔问题是一道经典的递归问题,它源于印度传说中的一个古老故事。
这个故事讲述了一个寺庙里有三根柱子,其中一根柱子上有64个盘子,从小到大依次放置。
寺庙里的僧人们每天都要把这些盘子从一根柱子移动到另一根柱子上,并且规定在移动过程中不能把大盘子放在小盘子的上面。
这个问题的挑战在于如何用最少次数将所有盘子从起始柱移动到目标柱。
1. 问题描述假设有三根柱子,分别为A、B、C,其中A柱上有n个圆盘,大小依次递增。
现在需要将A柱上的所有圆盘移动到C柱上,可以借助B柱作为中转站,但是需要满足以下条件:1. 每次只能移动一个圆盘;2. 圆盘可以放置在空柱或者比它大的圆盘上;3. 需要保证始终满足第2条规则。
求解该问题所需最少步骤。
2. 递归算法实现Hanoi塔问题可以使用递归算法来进行求解。
递归算法的基本思路是将一个大问题分解成若干个小问题,通过不断递归调用函数来解决这些小问题。
对于Hanoi塔问题,我们可以将其分解成三个步骤:1. 将n-1个圆盘从A柱移动到B柱;2. 将第n个圆盘从A柱移动到C柱;3. 将n-1个圆盘从B柱移动到C柱。
这样一来,原问题就被分解成了三个规模更小的子问题。
对于每一个子问题,我们可以继续按照同样的方式进行分解,直到规模变得足够小,可以直接求解为止。
下面是Hanoi塔递归算法的实现代码:```void hanoi(int n, char A, char B, char C) {if (n == 1) {cout << "Move disk " << n << " from " << A << " to " << C << endl;} else {hanoi(n - 1, A, C, B);cout << "Move disk " << n << " from " << A << " to " << C << endl;hanoi(n - 1, B, A, C);}}```其中,参数n表示当前需要移动的圆盘数量;参数A、B、C表示三根柱子的名称。
HANOI塔问题的递归解
HANOI塔问题的递归解HANOI塔问题是《数据结构》中用来介绍递归算法的最典型的例题。
本程序可同时将HANOI塔问题的解题步骤的中间结果显示在屏幕上和保存在文本文件中。
(后一点对于显示结果很多无法在一屏中显示时,特别有用)程序思路很简单,看注释就明白了。
/*Name: hanoi2.cAuthor: zhuqingDescription: HANOI塔问题的递归解Date: 06-08-03 11:44Copyright:*/#include#define N 5/* 原柱,中间柱,目标柱初值数组 */char a[]={'1','2','3','4','5'};char b[]={'0','0','0','0','0'};char c[]={'0','0','0','0','0'};int step=0;main(){FILE *fp;int i;if((fp=fopen("c:\\hanoi2.txt","w"))==NULL){printf("\nCannot open the file!\n");getch();exit(0);}printf("\n============ HANOI TOWER ============\n"); print(N);fprint(N,fp);move(N,a,b,c,fp);fclose(fp);getch();}/* 递归函数 */void move(int n,char a[],char b[],char c[],FILE* fp) {if(n>0){move(n-1,a,c,b,fp);c[n-1]=a[n-1];a[n-1]='0';print(N);fprint(N,fp);move(n-1,b,a,c,fp);}}/* 打印输出结果到屏幕的函数 */void print(n)int n;{int i;printf("\nSTEP%d",step++);printf("\na:");for(i=0;i<n;i++)printf("%3c",a[i]);printf("\nb:");for(i=0;i<n;i++)printf("%3c",b[i]);printf("\nc:");for(i=0;i<n;i++)printf("%3c",c[i]);printf("\n-------------------------------------\n"); }/* 打印输出结果到文本文件的函数 */void fprint(n,fp)int n;FILE *fp;{int i;fputs("\na:",fp);for(i=0;i<n;i++)fputc(a[i],fp);fputs("\nb:",fp);for(i=0;i<n;i++)fputc(b[i],fp);fputs("\nc:",fp);for(i=0;i<n;i++)fputc(c[i],fp);fputs("\n-------------------------------------\n",fp); }1 2。
hanoi塔递归算法 python
hanoi塔递归算法本文将介绍hanoi塔问题以及如何使用递归算法来解决它。
我们将使用Python语言来实现这个算法,并提供详细的步骤和代码。
什么是hanoi塔问题?hanoi塔问题是一个经典的数学问题,源自印度神话故事。
故事中,桩子上有三个针,最左边的针上叠放着64个金盘,大的在下,小的在上。
目标是将所有盘子从最左边的针移动到最右边的针上。
规则如下: 1. 只能一次移动一个盘子。
2. 每次移动时,只能将盘子叠放在更大的盘子上面。
递归算法解决hanoi塔问题递归算法是解决hanoi塔问题的最佳选择。
我们可以使用递归函数来实现这个算法。
下面是解决这个问题的步骤:1.定义一个递归函数hanoi,函数接受四个参数:盘子的数量n,起始针start,辅助针aux,目标针end。
2.如果n等于1,直接将盘子从起始针移动到目标针上。
3.否则,首先将n-1个盘子从起始针移动到辅助针上(目标针作为辅助针)。
4.然后将剩下的一个盘子从起始针移动到目标针上。
5.最后,将之前移动到辅助针上的n-1个盘子移动到目标针上(起始针作为辅助针)。
下面是使用Python语言实现这个算法的代码:def hanoi(n, start, aux, end):if n == 1:print(f"Move disk 1 from {start} to {end}")returnhanoi(n-1, start, end, aux)print(f"Move disk {n} from {start} to {end}")hanoi(n-1, aux, start, end)n = 3 # 盘子的数量hanoi(n, 'A', 'B', 'C') # 调用递归函数以上代码可以解决n个盘子的hanoi塔问题,并按照规则打印出每一步的移动过程。
代码解析让我们逐步解析一下上面的代码:1.首先定义一个名为hanoi的函数,它接受四个参数:盘子的数量n,起始针start,辅助针aux,目标针end。
java汉诺塔递归算法
java汉诺塔递归算法汉诺塔(Hanoi Tower)问题是一种经典的递归问题。
该问题是根据一个传说而命名的,传说是说在印度,有一个庙塔,庙塔内有三根针(柱子),在一根针上从下往上按照大小顺序排列着 n 个圆盘。
现在要求将这些圆盘从下方开始按照顺序移到另一根针上,但是在移动过程中,要求遵守以下条件:1.每次只能移动一个圆盘;2.每次移动,大盘不能放到小盘上面。
根据这个问题,我们可以使用递归算法来解决。
递归算法是一种将复杂问题分解成小问题、并通过解决小问题来解决复杂问题的方法。
下面是用Java编写的汉诺塔递归算法的代码:```javapublic class HanoiTowerpublic static void move(int n, char source, char target, char auxiliary)//当只有一个盘子时,直接将盘子从源柱子移动到目标柱子if (n == 1)System.out.println("Move disk 1 from " + source + " to " + target);return;}//将n-1个盘子从源柱子移动到辅助柱子,目标柱子作为辅助柱子move(n - 1, source, auxiliary, target);//将第n个盘子从源柱子移动到目标柱子System.out.println("Move disk " + n + " from " + source + " to " + target);//将n-1个盘子从辅助柱子移动到目标柱子,源柱子作为辅助柱子move(n - 1, auxiliary, target, source);}public static void main(String[] args)int n = 3; // 需要移动的盘子数量char source = 'A'; // 源柱子char target = 'C'; // 目标柱子char auxiliary = 'B'; // 辅助柱子move(n, source, target, auxiliary);}```上述代码中的 `move` 方法是递归方法,它接受参数 `n` 表示要移动的盘子数量,`source` 表示源柱子,`target` 表示目标柱子,`auxiliary` 表示辅助柱子。
hanoi塔递归算法c语言
hanoi塔递归算法c语言Hanoi塔是一种经典的数字益智游戏,它来源于法国数学家Lucas的BrainVita游戏,被称为“汉诺威塔问题”或“汉诺塔问题”。
该游戏由三个柱子和几个圆盘组成,最初时,圆盘按半径从大到小依次放在一个柱子上(逆序排列),游戏的目标则是将这些圆盘移动到另一个柱子上,最终使得其按半径从小到大依次排列。
在移动整个圆盘的过程中,必须遵循以下规定:1. 每次只能移动一个圆盘;2. 圆盘可以放置在任何柱子上;3. 不能将一个大的圆盘放在较小的圆盘之上。
为了解决这一难题,Hanoi塔问题引入了递归算法,这也是大多数编程语言中最常使用的算法之一。
在C语言中,Hanoi塔问题可以用以下代码实现:```c#include<stdio.h>void move(int n, char x, char y, char z){if(n == 1){printf("%c-->%c\n", x, z);}else{move(n-1, x, z, y);printf("%c-->%c\n", x, z);move(n-1, y, x, z);}}int main(){int n;printf("请输入盘子数:");scanf("%d", &n);printf("移动的步骤如下:\n");move(n, 'A', 'B', 'C');return 0;}```在这个程序中,我们首先定义了一个函数`move()`,该函数接受四个参数:圆盘的数量`n`和字母标识符`x`、`y`、`z`,它们分别代表三个柱子。
在函数中,我们使用了条件判断语句,如果只有一个圆盘,我们直接将其从柱子`x`移动至柱子`z`上。
否则,我们需要进行3个步骤:1. 将n-1个圆盘从柱子`x`移动至柱子`y`上;2. 将第n个圆盘从柱子`x`移动至柱子`z`上;3. 将n-1个圆盘从柱子`y`移动至柱子`z`上。
【NOIP2007普及组】Hanoi双塔问题
【NOIP2007普及组】Hanoi双塔问题看到这道汉诺双塔问题,我们首先应该理解一下汉诺(单)塔问题。
首先来看几个动画,三层的汉诺塔你总该会玩吧!最少需要7步。
那接下来我们看看四层的,看完过后你会不会有这样的感受,这不就是先移动一个三层塔,之后把第四层底座的移动过去,再把三层塔移动到第四层的底座上面吗,如果你发现了,那么说明你已经初步掌握了汉诺塔的规律。
这时,我们可以得到一个递推式:a[4] = a[3]+1+a[3];a[4] = 7+1+7;a[4] = 15;由此可得a[i] = a[i-1]+1+a[i-1];即,a[i] = 2*a[i-1] +1 .由于,a[1] = 1;所以我们可以进一步的递推得到一个汉诺塔通项计算公式:a[i] = 2^i - 1.这就完了吗?等等!不要高兴的太早,别忘了这道叫汉诺双塔,所以要在刚才得到的每一项都乘2,原因很简单,每两个尺寸相同的原盘不区分。
于是,我们得到了最后的递推公式:a[i] = 2*(2^i - 1) .下一步干什么呢,当然是要敲代码了!再稍等一下!我们来重新看一遍题,有没有发现什么坑?没错!就是数据的范围,1 <= n <= 200;2^200可是一个天文数字啊!就算是c中的long long也只能表示[-2^63,2^63-1]范围内的数,小编赶紧打开了Python(一种可以支持高精度的语言),计算的结果如下:没错!不要怀疑自己的眼睛,就是你所看到的这么大的数这道题的另一个考点就是高精度算法,很遗憾NOIP并不支持Python,我们只能通过自己编写大整数运算的算法来解决问题。
自定义一个结构体来解决大整数运算的问题,更多关于大整数的运算在这里就不介绍了。
以后会在算法部分为大家介绍。
给出完整的代码。
汉诺塔问题的程序实现(hanoi塔)
汉诺塔问题的程序实现(hanoi塔)问题重述:有三根柱A、B、C,在柱A上有N块盘⽚,所有盘⽚都是⼤的在下⾯,⼩⽚能放在⼤⽚上⾯。
现要将A上的N块盘⽚移到C柱上,每次只能移动⼀⽚,⽽且在同⼀根柱⼦上必须保持上⾯的盘⽚⽐下⾯的盘⽚⼩,输⼊任意的N,输出移动⽅法。
(注意:这是⼀个古⽼的传说,传说是如果把64个盘⼦由A柱移到了C柱的话,那么世界末⽇就到了,事实上如果要把64个盘⼦从A柱移到C柱的话,即使⽤计算机运算,也要计算数亿年,所以这个预⾔未必不是真实。
)【分析】我们可以这样考虑,当n=1时,我们只要直接将A柱的盘⼦移到C柱,当n>1时,我们可以先把n-1个盘⼦由A柱通过C柱移到B 柱,此时就可以把A柱剩下的最后⼀个盘⼦直接移到C柱,这样接下来只要把n-1个盘⼦通过A柱移到C 柱即可,如果就构成了递归的思路,我们可以定义个移动过程mov(n,a,b,c)表⽰将n个盘⼦从a通过b移到c1.只要求输出搬运的次数#includeusing namespace std;int m=0;void move(){m++;}void I(int n){if(n==1)move();else{I(n-1);move();I(n-1);}}int main(){I(3);cout<cout<<"输出完毕!"<return 0;}更加简单的⽅法!#includeusing namespace std;int fact(int n){if(n==1)return(1);elsereturn((2*fact(n-1)+1));}int main(){cout<}2.不仅要求输出搬运的次数,⽽且要输出每个步骤的详细搬运#includeusing namespace std;int m=0;void Move(int n,char x,char y){cout<<"把"<m++;}void Hannoi(int n,char a,char b,char c){if(n==1)Move(1,a,c);else{Hannoi(n-1,a,c,b);Move(n,a,c);Hannoi(n-1,b,a,c);}}int main(){int i;cout<<"请输⼊圆盘数"<cin>>i;Hannoi(3,'a','b','c');cout<<"总的搬运次数"<cout<<"输出完毕!"<return 0;}}另外⼀种不利⽤递归的解法(很抱歉,我⾃⼰也没调出来,实在太复杂了)#includeusing namespace std;//圆盘的个数最多为64const int MAX = 1;//⽤来表⽰每根柱⼦的信息struct st{int s[MAX]; //柱⼦上的圆盘存储情况int top; //栈顶,⽤来最上⾯的圆盘char name; //柱⼦的名字,可以是A,B,C 中的⼀个int Top()//取栈顶元素{return s[top];}int Pop()//出栈{return s[top--];}void Push(int x)//⼊栈{s[++top] = x;}} ;long Pow(int x, int y); //计算x^yvoid Creat(st ta[], int n); //给结构数组设置初值void Hannuota(st ta[], long max); //移动汉诺塔的主要函数int main(void){int n;cin >> n; //输⼊圆盘的个数st ta[3]; //三根柱⼦的信息⽤结构数组存储Creat(ta, n); //给结构数组设置初值long max = Pow(2, n) - 1;//动的次数应等于2^n - 1 Hannuota(ta, max);//移动汉诺塔的主要函数system("pause");return 0;}void Creat(st ta[], int n){ta[0].name = 'A';ta[0].top = n-1;//把所有的圆盘按从⼤到⼩的顺序放在柱⼦A 上for (int i=0; ita[0].s[i] = n - i;//柱⼦B,C 上开始没有没有圆盘ta[1].top = ta[2].top = 0;for (int j=0; jta[1].s[j] = ta[2].s[j] = 0;//若n 为偶数,按顺时针⽅向依次摆放A B Cif (n%2 == 0){ta[1].name = 'B';ta[2].name = 'C';}else //若n 为奇数,按顺时针⽅向依次摆放A C B {ta[1].name = 'C';ta[2].name = 'B';}}long Pow(int x, int y){long sum = 1;for (int i=0; isum *= x;return sum;}void Hannuota(st ta[], long max){int k = 0; //累计移动的次数int i = 0;int ch;while (k < max){//按顺时针⽅向把圆盘1 从现在的柱⼦移动到下⼀根柱⼦ch = ta[i%3].Pop();ta[(i+1)%3].Push(ch);cout << ++k << ": " <<"Move disk " << ch << " from " << ta[i%3].name <<" to " << ta[(i+1)%3].name << endl;i++;//把另外两根柱⼦上可以移动的圆盘移动到新的柱⼦上if (k < max){ //把⾮空柱⼦上的圆盘移动到空柱⼦上,当两根柱⼦都为空时,移动较⼩的圆if (ta[(i+1)%3].Top() == 0 ||ta[(i-1)%3].Top() > 0 &&ta[(i+1)%3].Top() > ta[(i-1)%3].Top()){ch = ta[(i-1)%3].Pop();ta[(i+1)%3].Push(ch);cout << ++k << ": " << "Move disk "<< ch << " from " << ta[(i-1)%3].name<< " to " << ta[(i+1)%3].name << endl;}else{ch = ta[(i+1)%3].Pop();ta[(i-1)%3].Push(ch);cout << ++k << ": " << "Move disk " << ch << " from " << ta[(i+1)%3].name << " to " << ta[(i-1)%3].name << endl; }}}}补充知识:【典型例题1】求阶乘n!#includeusing namespace std;int fact(int n){if(n==0)return(1);elsereturn(n*fact(n-1)); }int main(){cout<。
汉诺塔问题的求解程序
1.基于汉诺塔问题的求解程序,分别使用全局变量和局部变量来计算当塔中有n个盘子时需要进行多少步的盘子移动次数(例如当塔中有5个盘子时,需要移动31次)。
提示:当使用局部变量时,函数的原型可以为 long hanoi(int ,char,char,char),该函数的功能是完成hanoi塔的移动并返回其执行步数。
方法一:使用局部静态变量#include<stdio.h>long hanoi(int n,char one, char two, char three)/*该函数计算移动盘的步骤并返回移动步数 */{static long int count=0;/* 定义静态局部变量count,用以计算总共移动他多少次 */if(n==1){printf("move %c--> %c\n",one, three);count++;}else{hanoi(n-1,one,three,two);printf("move %c--> %c\n",one, three);count++;hanoi(n-1,two,one,three);}return(count);}void main(){int m=0;long int steps; /*定义长整型变量step用来装载hanoi函数的返回值*/printf("please input the number of diskes:");scanf("%d",&m);printf("the steps are following:\n");steps=hanoi(m,'A','B','C');printf("They need %ld steps to move\n",steps);}方法二:使用一般局部变量#include<stdio.h>long hanoi(int n,char one, char two, char three)/*该函数计算移动盘的步骤并返回移动步数 */{long int count1=0, count2=0;/* 定义局部变量count1,count2 */if(n==1)printf("move %c--> %c\n",one, three);else{count1=hanoi(n-1,one,three,two);printf("move %c--> %c\n",one, three);count2=hanoi(n-1,two,one,three);}return(count1+count2+1);}void main(){int m=0;long int steps; /*定义长整型变量step用来装载hanoi函数的返回值*/ printf("please input the number of diskes:");scanf("%d",&m);printf("the steps are following:\n");steps=hanoi(m,'A','B','C');printf("They need %ld steps to move\n",steps);}方法三:使用全局变量#include<stdio.h>long count=0;/*定义全局变量来统计移动步数 */void hanoi(int n,char one, char two, char three)/* 该函数计算移动盘的步骤*/{if(n==1){printf("move %c--> %c\n",one, three);count++;}else{hanoi(n-1,one,three,two);printf("move %c--> %c\n",one, three);count++;hanoi(n-1,two,one,three);}}void main(){int m=0;printf("please input the number of diskes:"); scanf("%d",&m);printf("the moving steps are following:\n"); hanoi(m,'A','B','C');printf("They need %ld steps to move\n",count); }。
用递归函数编写汉诺塔程序
用递归函数编写汉诺塔程序汉诺塔问题是一个经典的数学问题,可以用递归函数来解决。
汉诺塔问题的规则如下:有三个柱子,分别为左侧柱子、中间柱子和右侧柱子,初始时所有的盘子都放在左侧柱子上,从上往下依次编号为1、2、3、...、n,其中n为盘子的总数。
每次只能移动一个盘子,且盘子不能放在比它小的盘子上面。
目标是将所有的盘子都移动到右侧柱子上。
下面是用递归函数编写汉诺塔程序的步骤:Step 1:定义函数hanoi(n, left, middle, right),其中n表示盘子的个数,left表示左侧柱子,middle表示中间柱子,right表示右侧柱子。
Step 2:如果n等于1,则直接把盘子从左侧柱子移动到右侧柱子,输出提示信息。
Step 3:否则,先把n-1个盘子从左侧柱子移动到中间柱子上,调用函数hanoi(n-1, left, right, middle)。
Step 4:把最后一个盘子从左侧柱子移动到右侧柱子上,输出提示信息。
Step 5:最后把n-1个盘子从中间柱子移动到右侧柱子上,调用函数hanoi(n-1, middle, left, right)。
完整代码如下:```def hanoi(n, left, middle, right):if n == 1:print(f'Move disk {n} from {left} to {right}')else:hanoi(n-1, left, right, middle)print(f'Move disk {n} from {left} to {right}')hanoi(n-1, middle, left, right)hanoi(3, 'left', 'middle', 'right')```输出结果如下:```Move disk 1 from left to rightMove disk 2 from left to middleMove disk 1 from right to middleMove disk 3 from left to rightMove disk 1 from middle to leftMove disk 2 from middle to rightMove disk 1 from left to right```可以看到,程序按照规则把所有盘子都移动到了右侧柱子上。
Hanoi双塔问题(noip2007pj)
全国信息学奥林匹克联赛(NOIP2007)复赛普及组
4.Hanoi双塔问题
hanoi.pas/c/cpp
【问题描述】
给定A,B,C三根足够长的细柱,在A柱上放有2n个中间有空的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形)。
现要将这些国盘移到C柱上,在移动过程中可放在B柱上暂存。
要求:
(1)每次只能移动一个圆盘;
(2) A、B、C三根细柱上的圆盘都要保持上小下大的顺序;
任务:设An为2n个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出An。
【输入】
输入文件hanoi.in为一个正整数n,表示在A柱上放有2n个圆盘。
【输出】
输出文件hanoi.out仅一行,包含一个正整数,为完成上述任务所需的最少移动次数An。
【限制】
对于50%的数据, 1<=n<=25
对于100% 数据, 1<=n<=200
【提示】
设法建立An与An-1的递推关系式。
第1页共6页。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
/*拿到这个题目首先想到的是经典的“汉诺塔问题”,
但是那是汉诺“单塔”,而这道题目是汉诺“双塔”,于是可以用
贪心策略,把两块相同大小的圆盘看成一个圆盘,于是问题就简化成“单塔”了,
而hanoi塔简单的做法就是递归,递归方程为f(n)=2*f(n-1)+1,道理很简单,当前
n个圆盘总的移动次数可以看成y由n-1个圆盘移动基础上得来的,而具体关系就是
f(n)=f(n-1)+f(n-1)+1,例如,n个盘都在A塔上,先把A上面的n-1个盘移到B盘上,用了
f(n-1)次,再把A盘上最底下的盘放到C盘上,用1次,最后,再把B盘上的盘都移到C盘
上,用f(n-1)次,总共为2*f(n-1)+1次。
而为了简化程序,可以把递归改为迭代,用一个循环加数组存储搞定,省时省空间*/
#include<stdio.h>
int main()
{int f[100],i,n;
scanf("%d",&n);
f[1]=1;
for(i=2;i<=n;i++)f[i]=2*f[i-1]+1; //递归公式f[n]=f[n-1]*2+1;
printf("%d",f[n]*2); //在单塔的基础上乘2
return 0;
}。