当前位置: 首页 > 科技观察

用Go语言实现Hanota算法

时间:2023-03-21 01:15:46 科技观察

游戏由来相传最早发明这道题的人是法国数学家EdouardLucas。在世界中心贝拿勒斯(印度北部)的避难所,三根镶有宝石的针被插入黄铜板上。印度教大神梵天开天辟地时,将64枚金片自下而上组装在一根针上,这就是所谓的河内塔。无论白天黑夜,总会有和尚按照以下规则移动这些金块:一次只能移动一枚,无论是在哪根针上,小的都必须在大的上面片。僧人预言,当所有金块从梵天宝针上移到另一根宝针上时,世界将在雷霆中毁灭,梵天塔、寺庙和众生也将毁灭。这个传说有很多变体。虽然不知道是谁创造的,但它留下的数学问题非常经典。遗留数学知识:金片数量与移动步数的关系为2?–1:1个金片所需步数为2的1次方减1,2个金片所需步数为2的2次方减去13个金子取2的3次方减1...n个金子取2的n次方减1步如果传说是真的,和尚需要2??-1步才能完成这个任务;假设他们每秒移动一块金子,则需要5849亿年才能完成。整个宇宙只有137亿岁,现在毁灭宇宙还为时过早。..游戏规则分析假设这个游戏有3个木桩,分别是A、B、C,需要移动的是珠子,其中一列已经有N个有序的珠子,最大的在最下面,珠子越来越小并且按顺序变小。其他2个是空列。基本条件:一次只能移动一颗珠子。小珠子必须在大珠子上面。初始状态如下图所示:最终目标是将列上的所有珠子移动到另一列。如下图:游戏实现思路清空大脑,先想想最简单粗暴的解决逻辑:把珠子当成一个整体。满足大珠在下的基本条件,必须把A上最大的珠子放空,然后把最大的珠子放在C柱上。(假设珠子的个数为N)如果要把它移到C列,首先要实现的是把N-1个珠子全部移到B列,这样第N个珠子(也就是第最大的珠子)可以移动到C柱上。将N-1颗珠子移到B列,因为大珠子在最下面,小珠子在上面,所以这N-1颗珠子是有序排列在B列的。最后,把B柱上的N-1颗珠子移到C柱上,就完成了最终的目标。实现第一步:将A上的N-1个珠子移到B上。为什么先把N-1移到B?因为你最后的实现是把所有的珠子从A移到C,顺序不能变。只有大的在下,小的在上。那么最大的珠子必须先移到C,否则条件不成立。要将最大的珠子从A移动到C,必须释放A上的最大珠子,即必须移除最大珠子上方的所有珠子。而你只有3根柱子,C上不能有其他的珠子,否则不合格,所以这N-1颗珠子只能放在B上,依然会有序。第二步将A上的第N个珠子(最大的珠子)移到C上,简单到一步把A上最大的珠子移到C上。如下。第三步将B上的N-1个珠子移到C上。提示:要实现将N-1个珠子移到C上,是不是先找到其中最大的珠子,然后先把最大的珠子移动?所以这里的话其实变成了重复第一步和第二步,从这N-1个珠子中找出最大的一个,移到C,重复。第三步其实相当于改变需求。假设K=N-1,此时B列有K个珠子,A列是空的,C列的珠子最大,所以B列有K个珠子就好像是空的。第一步将B上的K-1个珠子移动到A。第二步将B上的第K个珠子移动到C。第三步将A上的K-1个珠子移动到C,如下所示。首先找到最大的剩余珠子(本演示中为4号)。然后移动它。循环重复以上步骤,直到只剩下最后一颗(最小的)珠子,直接移到C,游戏结束。辅助栏目什么是辅助栏目?假设你现在所有的珠子都在A上移动,目标是把它们移动到C上,那么B就是这N-1个珠子的辅助列。因为他们只能暂时留在这里,否则就不符合游戏规则。这里需要先找到辅助支柱,不要想着怎么实现,先理清逻辑。要实现从A到B的运动,C是辅助柱。要实现从A到C的运动,那么B就是副支柱。要实现从B到C的移动,A是辅柱。Golang实现从上面的分析我们可以看出,这其实是一个循环重复的操作,和递归很相似,可以用递归来实现。要使用递归,有两个必要条件。找出递归的公式。找到退出条件。在这个游戏中,退出条件是直接移动到只有一颗珠子的C柱上。那么什么是递归公式呢?根据上面的逻辑分析,可以分解为三个步骤:第一步,将{N-1个珠子}从A移到B第二步,将{第N个珠子}从A移到C第三步,移动{剩下的N-1颗珠子}从B到C以下是Golang实现的伪代码packagemainimport"fmt"//记录游戏步数varcountint=0funcmain(){beadNum:=5//This是珠子的初始数量fmt.Printf("ThisisaHannukahgamewith%dbeads\n\r",beadNum)hanoi(beadNum,"A","B","C")fmt.Printf("Gameover:%dstepsintotalspent\n\r",count)}//Hannukahgamefunchanoi(beadNumint,pillarAstring,pillarBstring,pillarCstring){ifbeadNum==1{//如果只有一个珠子,从A移动到C,gameovermove(beadNum,pillarA,pillarC)}else{//第二步:将N以上(即N-1判断)的所有盘子从A移动到B。此时,C是中转站hanoi(beadNum-1,pillarA,pillarC,pillarB)//第二步:将第N个盘子从A移动到Cmove(beadNum,pillarA,pillarC)//第三步:移动剩下的B上n-1个盘从B到C,此时A为中转站hanoi(beadNum-1,pillarB,pillarA,pillarC)}}//移动beadsfuncmove(beadNumint,pillarFromstring,pillarTostring){count+=1fmt.Printf("Step%d:beadof%dfrom%smoveto%s\n\r",count,beadNum,pillarFrom,pillarTo)}感谢您阅读本文,如果您认为文章写的不错,请关注我