56 汉诺塔问题的第m步(汉诺塔问题的总结)

56 汉诺塔问题的第m步

作者: Turbo时间限制: 3S章节: 递归

问题描述 :

给定三根杆A、B、C和大小不同的几个盘子。这些盘子按尺寸递减顺序套在A杆上,最小的在最上面。现在的任务是把这些盘子从A杆移到C杆且保持原来堆放顺序。在实现任务时,每次只能移动一个盘子,且任何时刻不允许大的盘子放在小的盘子上面,B杆可以作为辅助存放杆。求:总共有n个圆盘时,搬动过程中的第m步是从哪个杆到哪个杆。

 

输入说明 :

你的程序需要从标准输入设备(通常为键盘)中读入多组测试数据。每组输入数据由一行组成,每行输入一个整数表示盘子数n,1≤n≤10,以及步数m,两个数据之间以一个空格分隔。行首和行尾没有多余的空格,两组数据之间也没有多余的空行。

输出说明 :

对每组测试数据,你的程序需要向标准输出设备(通常为启动该程序的终端)依次输出一行对应的答案,该行中输出第m步移动的情况,如第m步是从A移到B,则输出“A--B”(不包括引号)。如果移动过程不存在第m步,则输出“none” (不包括引号)。

两组数据之间无空行,第一组前及最后一组后也无空行。

 

输入范例 :

2 3
2 4

输出范例 :

B--C
none

 

先来回顾下汉诺塔问题。讲真的,作为一个科班的CS学生,大二的时候一致没有搞懂汉诺塔问题,今天必须和它做一个了断。

我们先根据游戏规则,从最简单的情况分析一波:

图一 最简单的情况

 

 第一种情况如图一所示,这种情况最简单了,按照游戏规则,我们可以直降将A上的盘子移动到C上面。问题得到解决(虽然这是最简单的问题,

但是这个问题是以后大问题的子问题)。

 

 

 图二:两个盘子

第二种情况如图二所示:这个问题变得稍微复杂了一些,按照游戏规则,我们只能先移动1(不要忘了,我们是要把所有的盘子按照规则从A移动到C)。

为了使步数最少,我们先将盘子1移动到B(借助B),然后将大盘子2直接移动到C,最后再将B上的盘子1移动到C。问题得到解决。

图三:三个盘子的情况

 第三种情况如图三所示,为了将三个盘子从A移动到C,我们要动些脑筋了。

当然了,我们可以用手模拟一下,如下(其实完全可以省略……,我们还是动手模拟下)

首先我们要达成一个共识,

A->B(将A上的1移动到B上)

A->C(将A上的2移动到C上)

C->B(将C上的1移动到B上)

 A->C(将A上的1移动到C上)

图四

 到这里我们可以先停下来看看我们做了些什么。

简单总结下来就是,我们想了一些办法,经过某种操作(不要怀疑你的做法),使得盘子1和2从A上移动到了B上,

然后我们可以将最大的盘子从A上直接移动到C上。问题似乎有了进展,但是还没有解决。我们下一步要解决的是

将盘子1和2移动到C上。

B->A(将B上的1移动到A上)

B->C(将B上的2移动到C上)

图5

 此时,问题显然已经得到了解决。但是刚刚的感觉好像再重复着某些动作。是的,我们必须把重复的动作找出来。

是这样的,当A上有三个盘子的时候(图三),我们先是想办法将1和2移动到B上,然后将A上最大的盘子移动到C上。(图四)

接下来的问题就变成了将盘子1和2借助于A移动到C上,我们先是将1移动到A上,然后将B上剩下的最大的盘子2移动到了C上(图5)。

动作真的非常重复,我没有什么好的语言去总结,但是规律已经很明显了。

0、想办法将A上的盘子全部移动到C上面

1、首先将A上除了最大盘子以外的盘子移动到B上(借助B)

2、然后将A上最大的盘子直接移动到C上

3、想办法将B上的盘子全部移动到C上面(其实问题已经回到了0,变得只是规模和充当被借助的对象)

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <math.h>
 4 #include <string.h>
 5 #include <ctype.h>
 6 
 7 #define maxn 1005
 8 
 9 
10 int n,m,step;
11 void Hanoi(int n,char x,char y,char z);
12 void move(char x,char y);
13 int main(){
14 
15     
16     char x,y,z;
17     x = 'A';
18     y = 'B';
19     z = 'C';
20     while(scanf("%d %d",&n,&m)!=EOF){
21         step = 0;
22         Hanoi(n,x,y,z);    
23         if(step<m||m<=0){
24             printf("none\n");
25         }
26     }
27     
28     
29     return 0;
30 }
31 
32 void Hanoi(int n,char x,char y,char z){
33     if(n == 1){
34         //只需要移动一个盘子
35         step++;
36         move(x,z);//将变量x代表的柱子上的盘子从x移动到z所代表的柱子上z
37         return;
38     }
39 
40     Hanoi(n-1,x,z,y);//首先将A上除了最大盘子以外的盘子移动到B上(借助C)
41     step++;
42     move(x,z);//将变量x代表的柱子上的盘子从x移动到z所代表的柱子上z
43     Hanoi(n-1,y,x,z);    
44 }
45 
46 void move(char x,char y){
47     if(step == m){//只有在第m步中输出
48         printf("%c--%c\n",x,y);    
49     }
50 }

猜你喜欢

转载自www.cnblogs.com/ManOK/p/12595516.html
今日推荐