汉诺塔问题

来源:互联网 发布:vr编程用什么语言 编辑:程序博客网 时间:2024/06/18 09:02

什么是汉诺塔:https://zh.wikipedia.org/zh-hans/%E6%B1%89%E8%AF%BA%E5%A1%94

汉诺塔是理解递归的绝佳例子,


最佳的方案一定是按照以下三步来的:

(1)先把from的前n-1个盘子放到mid柱子上,

(2)然后把from的最后一个放到to最低端

(3)把mid的n-1个放到to上面(因为to下面是最大的,所以完全可以忽略他们的存在)

这个问题就像把“大象放到冰箱有几步”一样。从上面可以看到(1)(3)步明显是总问题的一个子问题,只是步数差1,元素柱子,目标柱子这几个因素不同而已,其他都是一样的,自然而然就想到了递归和DP


先来看n层完成游戏需要多少步



如果我们想打印游戏移动的路径呢?

对于传统的汉诺塔游戏我们做一个拓展,我们有从大到小放置的n个圆盘,开始时所有圆盘都放在左边的柱子上,按照汉诺塔游戏的要求我们要把所有的圆盘都移到右边的柱子上,请实现一个函数打印最优移动轨迹。

给定一个int n,表示有n个圆盘。请返回一个string数组,其中的元素依次为每次移动的描述。描述格式为: move from [left/mid/right] to [left/mid/right]。

测试样例:
1
返回:move from left to right
import java.util.*;/* * 完美的递归思想 */public class Hanoi {ArrayList<String> rst = new ArrayList<String>();    public ArrayList<String> getSolution(int n) {        getSolution(n, "left", "mid", "right");    return rst;    }private void getSolution(int n, String from, String mid, String to) {if(n == 1) {rst.add("move from " + from + " to " + to);return;}// 把大象装到冰箱需要三步,这里也是一样的递归思路getSolution(n-1, from, to, mid);getSolution(1, from, mid, to);getSolution(n-1, mid, from, to);}}


如果想判断某个状态是不是通往答案的一种状态呢?

有一个int数组arr其中只含有1、2和3,分别代表所有圆盘目前的状态,1代表左柱,2代表中柱,3代表右柱,arr[i]的值代表第i+1个圆盘的位置。比如,arr=[3,3,2,1],代表第1个圆盘在右柱上、第2个圆盘在右柱上、第3个圆盘在中柱上、第4个圆盘在左柱上。如果arr代表的状态是最优移动轨迹过程中出现的状态,返回arr这种状态是最优移动轨迹中的第几个状态。如果arr代表的状态不是最优移动轨迹过程中出现的状态,则返回-1。

给定一个int数组arr及数组的大小n,含义如题所述,请返回一个int,代表所求的结果。

测试样例:
[3,3]
返回:3
package l2;import java.util.ArrayList;import java.util.List;/* * 可以完整的递归一遍求 */public class Hanoi {int rst = -1, cnt = 0;List<Integer> l1 = new ArrayList<Integer>();List<Integer> l2 = new ArrayList<Integer>();List<Integer> l3 = new ArrayList<Integer>();List<List<Integer>> ll = new ArrayList<List<Integer>>();    public int chkStep(int[] arr, int n) {    for(int i=n; i>0; i--)    l1.add(i);    ll.add(l1);    ll.add(l2);    ll.add(l3);        getSolution(arr, n, l1, l2, l3);    return rst+1;    }    private void getSolution(int[] arr, int n, List<Integer> from, List<Integer> mid, List<Integer> to) {if(rst != -1)return;if(n == 1) {int remove = from.remove(from.size()-1);to.add(remove);boolean f = true;for(int i=0; i<arr.length; i++)if(!ll.get(arr[i]-1).contains(i+1)) {f = false;break;}if(f) {rst = cnt;}cnt ++;return;}// 把大象装到冰箱需要三步,这里也是一样的递归思路getSolution(arr, n-1, from, to, mid);getSolution(arr, 1, from, mid, to);getSolution(arr, n-1, mid, from, to);}}



0 0