hanoi汉诺塔问题

来源:互联网 发布:windows美化大师电脑 编辑:程序博客网 时间:2024/05/01 08:25

Hanoi塔问题是个古典的数学问题,如果能够想清楚这个问题,那我相信你的逻辑思维已经很不错了,问题是这样的:

古代有一个梵塔,塔内三个座A,B,C,A上有64个盘子,从小到大,从上而下依次排列,有人想把这64个盘子从A移动到C,每次只能移动一个盘子,并且移动过程中始终保持三个座上小盘在上,大盘在下,请问该怎么移动?

刚拿到这个问题,绝对是很难从头到尾想清楚详细的步骤,当然除非你的大脑比电脑的运算能力还要强千百倍,那就不用再往下看了,首先我们可以假设:

如果有另外一个人帮我把63个盘子从A移动到B,那么我就可以只移动1个盘子从A到C,然后再让这个人帮我把63个盘子从B移动到C,不就实现了吗?那么问题来了,第二个人又要怎样将盘子从A移动到B,他就只能叫第三个人帮他将62个盘子从A移动到C,那么他就可以将1个盘子从A移动到B,然后再让第三个人将62 个盘子从C移动到B……以此类推

这样大概的步骤就有点轮廓了,下面就是程序了,虽然我们知道这个步骤,但是这个递归程序到底该怎么写呢?

(1)叫第二个人将n-1个盘子从A移动到B

(2)自己将1个盘子从A移动到C

(3)叫第三个人将n-1个盘子从B移动到C

我们想象一下,第一个人将n个盘子从A移动到C,首先需要第二个人将n-1个盘子从A移动到B,而第二个人将n-1个盘子从A移动到B,又需要第三个人将n-2个盘子从A移动到C,所以我们会发现在完成第一步的过程中,他们一直是将盘子从A到B和C之间不停的切换。

而第三步,第二个人需要将n-1个盘子从B移动到C,首先我们需要第三个人将n-2个盘子从B移动到A,然后他才能将一个盘子从B移动到C,接着第三个人需要将n-2个盘子从A移动到C,首先他需要第四个人将n-3个盘子从A移动到B,然后他才可以将一个盘子从A移动到C,以此类推,我们可以发现第三步其实都是A,B座来回切换。

那么我们就可以这样编写程序了

(1)定义我们自己移动盘子的函数

void move(char x , char y)
32 {
33 printf("%c ——> %c \n", x , y);
35 }
(2)定义下一个人需要移动盘子的函数

  • 叫第二个人将n-1个盘子从A通过C移动到B
  • 自己将1个盘子从A移动到C
  • 叫第三个人将n-1个盘子从B通过A移动到C


 void hanoi(int i , char A , char B , char C)    函数(盘子个数,开始点,过度点,最终点)
18 {
19 if(i == 1)
20 {
21 move(A , C);
22 }
23 else
24 {
25 hanoi(i - 1 , A , C , B); 叫第二个人将n-1个盘子从A通过C移动到B
26 move(i , A , C); 自己将1个盘子从A移动到C
27 hanoi(i - 1 , B , A , C); 叫第三个人将n-1个盘子从B通过A移动到C
28 }
29 }

C程序:

 #include <stdio.h>
2
3 void hanoi(int i , char A , char B , char C);
4 void move(char x , char y);
5
6 int main()
7 {
8 int n ;
9 printf("请输入n的值:");
10 scanf("%d",&n);
11
12 hanoi(n , 'A' , 'B' , 'C');
13
14 return 0 ;
15 }
16
17 void hanoi(int i , char A , char B , char C)
18 {
19 if(i == 1)
20 {
21 move(A , C);
22 }
23 else
24 {
25 hanoi(i - 1 , A , C , B); //B C座切换
26 move(i , A , C);
27 hanoi(i - 1 , B , A , C); //A B座切换
28 }
29 }
30
31 void move(char x , char y)
32 {
33 printf("%c ——> %c \n", x , y);
35 }
java 程序

import java.util.Scanner;public class Move {public static void main(String[] args) {System.out.println("input the number of diskes:");Scanner scan = new Scanner(System.in);Integer m = Integer.valueOf(scan.nextLine());Move move = new Move();move.hanoi(m,'a', 'b','c');}public void move(char x,char y){System.out.println(x+"--->"+y);}public void hanoi(int n,char one,char two,char three){if(n==1){move(one,three);}else{hanoi(n-1,one,three,two);move(one,three);hanoi(n-1,two,one,three);}}}
将2个盘子移动到C,需要3步
A--B,A--C,B--C
将3个盘子移动到C,需要7步
A--C,A--B,C--B,A--C,B--A,B--C,A--C
将n个盘子移动到C,需要2^n-1步,假设,每移动一次需要1秒,那么移动(2^64-1)次需要(2^64-1)秒,大约6*10^11年,相当于6000亿年,有人戏称,当移动完这些盘子的时候,世界末日也就要到了。


这是我看了hanoi(汉诺)塔问题之后的理解,如果有其他的见解,希望可以分享一下,希望对看到的人有所帮助。




0 0