前言:
我又来啦,今天在逛贴吧的时候,看到了一个有意思的题,激起了我的兴趣,想了好久,才明白了这道题,所以趁着热乎,就到这里记录一下啦。
问题描述
汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,任何时候,在小圆盘上都不能放大圆盘,且在三根柱子之间一次只能移动一个圆盘。问应该如何操作?
问题解析
初看这道题呀,就是觉得这不是有病吗,闲着没事干非要换来换去的,要求还这多,哼,气死老娘了。哈哈,开个小玩笑。这道题呀,也正是有了这些条件,才让这道题变得有趣起来。这也正是说明了古代那些数学家真的是奇思妙想呀,哈哈。打个小趣,下面开始正式解决这道题。
我们先画个图来说明这个完成流程吧,能看的更直观一些,图画的坑可能有点丑,但纯是手工操作you,没想到我也有画画的天赋哈。
亮图,天霸动霸tua:
好啦,流程就是这样啦,我们先把63个盘子看成整体,这样就等于只有两个盘子,这样就容易很多了,我们只要完成这两个盘子的移动就可以了。这样一步步下去直到最后一个盘子,完成操作。
知道了流程以后,接下来就要考虑这个代码该怎么写了。
设n代表盘子的总数,x,y,z代表三个柱子。那我们每次把n-1个盘子当做一个整体,这就是一种分治求解子问题的思想。
这道题我们就可以用递归的思想思考了。何为递归呢?递归就是一种思想。比如,求解斐波那契额数列,我们可以通过递归来实现,一步步回溯求解f(n)+f(n-1),在一步步返回。
在在求f(n, one,other)的时候,你就默认f(n -1, one, other)已经被求出来了——至于怎么求的,这个是计算机通过回溯求出来的。
递归的使用最关键的两个点:
- 递归的结束条件(不写会死循环,TLE)
- 递归最后一层和其他有关系的层的关系怎样用非递归函数来表达
代码样例
private static int count=0;
public static void move_log(int id,char from,char to)
{
System.out.println("step " + (++count)+ "move "+ id+ "from" + from +"->" + to);
}
public static void hanta(int n,char x,char y,char z)
{
if(n == 0)
{
return;
}
hanta(n-1,x,z,y);
move_log(n,x,z);
hanta(n-1,y,x,z);
}
public static void main(String[] args) {
int n;
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
hanta(n,'A','B','C');
}
至此这个算法就结束了。