【JavaOJ】汉诺塔问题

简介: JavaOJ & 汉诺塔问题

JavaOJ & 汉诺塔问题

汉诺塔定义:


通俗地来讲就是:


一堆盘子从一根柱子全部挪向另一根柱子

并且有如下规则:

一次只能移动一个盘子

大盘子不能叠在小盘子之上

老规矩,我们先学会思想

1. ”整体性假设“思想

在这里不给动图以及不给手解方法的原因是:真的很难理解的了,即使会怎么摆了,但是也可能不会是正确解法。


现在是《幻想时刻》


假设,我说假设!


如果如果如果有一个方法hanoi(x)(x代表总盘子数),它可以帮我们将A柱子的所有挪向C柱子*


那么那么那么是不是hanoi(x - 1)就可以将A柱子的x - 1个盘子挪向B柱子!是不是?



然后A柱子剩余的一个盘子是不是就可以直接放在C柱子上?



那么接下来请问,hanoi(x - 1)是不是也有能力让B柱子的x - 1个盘子子全部挪到C盘子上?



*没错,我们幻想了一下,发现只要知道x - 1个盘子怎么移动,那么我就可以利用刚才的方法,去挪动x个盘子。


那么那么那么是不是我们会挪一个盘子




就会挪两个盘子,= =》就会挪三个盘子,= = = = = = = = = = = =》

那就会挪x个盘子!


2. 代码设计

参数:

三根柱子:ABC

n个盘子。

public class Hanata {
    public static int count = 1;   //在自己类之中,静态的全局性变量
    public static void hanoi(int n, char pos1, char pos2, char pos3){
        //1. ************************************
        if(n == 1) {
            move(pos1, pos3);
            return; //return !!!
        }
        //2. ************************************
        hanoi(n - 1, pos1, pos3, pos2);
        move(pos1, pos3);
        hanoi(n - 1, pos2, pos1, pos3);
    }
        //3. ************************************
    public static void move(char pos1, char pos2) {
        System.out.println("第" + count++ + "次移动: " + pos1 + " -> " + pos2 + " ");
    }
  //4. ************************************
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        hanoi(n,'A','B','C');
    }
}


2.1 区域3:

public static void move(char pos1, char pos2) {
    System.out.println("第" + count++ + "次移动: " + pos1 + " -> " + pos2 + " ");
}

移动盘子并且打印出来

2.2 区域1:

if(n == 1) {
        move(pos1, pos3);
        return; //return !!!
    }


hanoi(1) ==> 第一个盘子的放法,我们默认A(pos1)柱子为起始柱

通过测试,我们改变pos1,pos3,为其他,只是决定了所有盘子初始位置,以及第一个盘子挪向哪。

那么第一个盘子放在C(pos3)柱子就好了

这也是递归出口!

2.3 区域2:

hanoi(n - 1, pos1, pos3, pos2);
    move(pos1, pos3);
    hanoi(n - 1, pos2, pos1, pos3);


Ⅰ. 跟刚才的想法一致,我们将A(pos1)的 n - 1 个盘子通过C(pos3)挪到B(pos2)

通过上面动图思想的分析,不难发现,总有一个中间柱子充当媒介,帮助n-1个盘子的挪动


Ⅱ. 将A(pos1)放置到C(pos3)


Ⅲ.将B(pos2)的n-1个盘子以相同的方式通过A(pos1)挪到C(pos3)


2.4 测试

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    int n = scan.nextInt();
    hanoi(n,'A','B','C');
}



这里为什么是31次呢,其实就是 2n -1

一个盘子要1次

那么两个要1 + 1 + 1 = 3

那么三个要 3 + 1 + 3 = 7

那么四个要 7 + 1 + 7 = 15

即an = 2an-1 + 1; ==>等比数列 ==》 通式:an = 2 n - 1;*

3. 用C实现后再VS2022测试(有时停函数与清屏,更加好观察)

C语言实现汉诺塔自走版


代码有点长,不做为重点,只是为了测试



汉诺塔自走版视频


#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<Windows.h>
#include<stdlib.h>
#define NUM 5
int count = 0;
typedef struct hanuota
{
  char X;
  char Y[NUM+1];
  int count;
}sh;
void print(sh* pa, sh* pb, sh* pc)
{
  sh s[3] = { *pa,*pb,*pc };
  int i = 0;
  int j = 0;
  sh tmp;
  for (i = 0; i < 3; i++)
  {
  for (j = 1; j < 3 - i; j++)
  {
    if (s[j].X < s[j - 1].X)
    {
    tmp = s[j - 1];
    s[j - 1] = s[j];
    s[j] = tmp;
    }
  }
  }
  for (i = 0; i < 3; i++)
  {
  printf("柱%c:%s\n", s[i].X, s[i].Y);
  }
  Sleep(500);
}
void step(int n, sh* pa, sh* pb, sh* pc)
{
  if (n == 1)
  {
  system("cls");
  printf("第%2d步:%c-->%c\n\n", ++count, pa->X, pc->X);
  pc->Y[(pc->count)] = pa->Y[(pa->count)-1];
  pa->Y[(pa->count)-1] = ' ';
  (pc->count)++;
  (pa->count)--;
  print(pa, pb, pc);
  }
  else
  {
  step(n - 1, pa, pc, pb);
  {
    system("cls");
    printf("第%2d步:%c-->%c\n\n", ++count, pa->X, pc->X);
    pc->Y[(pc->count)] = pa->Y[(pa->count)-1];
    pa->Y[(pa->count)-1] = ' ';
    (pc->count)++;
    (pa->count)--;
    print(pa, pb, pc);
  }
  step(n - 1, pb, pa, pc);
  }
}
init(sh* pa)
{
  int i = 0;
  int j = 0;
  for (i = NUM-1; i >=0; i--,j++)
  {
  pa->Y[j] = 'A' + i;
  }
}
int main()
{
  int n = 0;
  sh a = { 'A',{0},NUM }, b = { 'B',{0},0 }, c = { 'C',{0},0 };
  sh* pa = &a, * pb = &b, * pc = &c;
  init(pa);
  print(pa, pb, pc);
  Sleep(2500);
  step(NUM, pa,pb,pc);
  system("cls");
  print(pa, pb, pc);
  return 0;
}

文章到此结束!谢谢观看 —>内容参考【比特科技】

可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆!


这是我的代码仓库!(在马拉圈的23.2里)代码仓库


汉诺塔 · Java版代码位置


汉诺塔电脑自走版 · C代码位置


目录
相关文章
|
7月前
|
算法
06_用栈来求解汉诺塔问题
06_用栈来求解汉诺塔问题
汉诺塔问题
汉诺塔(Tower of Hanoi),又称河内塔,是一个源于印度古老传说的益智玩具。大梵天创造世界的时候做了三根柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。
82 0
|
C语言
汉诺塔问题(解出来了带你看洛丽塔)
汉诺塔问题(解出来了带你看洛丽塔)
177 0
汉诺塔+小青蛙跳台阶---《递归》
汉诺塔+小青蛙跳台阶---《递归》
108 0
递归函数之汉诺塔(附:raptor汉诺塔)
递归函数之汉诺塔(附:raptor汉诺塔)
|
C语言
【C】青蛙跳台阶和汉诺塔问题(递归)
【C】青蛙跳台阶和汉诺塔问题(递归)
128 0
【C】青蛙跳台阶和汉诺塔问题(递归)
|
C++
【C/C++】汉诺塔问题
## 汉诺塔问题相传来源于印度教的天神汉诺。据说汉诺在创造地球时建了一座神庙,神庙里面有三根柱子,汉诺将64个直径大小不同的盘子按照从大到小的顺序依次放置在第一个柱子上,形成金塔(即汉诺塔)。天神汉诺每天让庙里的僧侣们将第一根柱子上的64个盘子借助第二根柱子全部移动大第三根柱子上,并说:“当这64个盘子全部移动到第三根柱子上时,世界末日也就要到了!”这就是著名的汉诺塔问题。
136 0
【C/C++】汉诺塔问题