1.算法实例——汉诺塔问题
思路:
三个柱子分别为A、B、C,初始状态为盘子都在A上,要求把A的盘子全部移动到C,则需要分三步执行:
① 将A中最上层的n-1个盘子从A移到B
② 将A中最下面也是最大的1个盘子从A移到C
③ 再将之前从A移到B暂存的n-1个盘子从B移动到C
上述三个步骤中,仅有步骤②是直接执行,而步骤①和步骤③都要通过递归实现。
步骤①中,如何把n-1个盘子从A移到B?这可以看成一个新的子问题,而这个子问题跟原问题是一样的,所以我们可以利用递归,再次重复上述的三个步骤就行了,但是,要如何设置参数呢?首先,这个子问题中只有n-1个盘子,所以我们只需要把n改为n-1,其次,要想把n-1个盘子从A移到B,就得先把n-2个盘子从A移到C,依次类推往下,直到最后只需要将一个盘子从A移动到C,然后执行步骤②。
步骤③的原理类似于同步骤②。
具体实现:
public static void move(Tower A,Tower B,Tower C){
int[] count = {0};
System.out.println(A.toString()+";"+B.toString()+";"+C.toString());
move(A.size(),A,B,C,count);
}
接收三个Tower类型参数,对移动步数进行统计,默认为0,打印三个传入参数的初始状态后调用move()函数。
private static void move(int num, Tower a, Tower b, Tower c,int[] count) {
if(num == 1){
int m = a.remove();
c.add(m);
count[0] ++;
System.out.println(count[0]);
System.out.println("将"+m+" "+ "从"+a.name+""+"柱 移动到"+" "+c.name+" "+"柱");
Tower first = null,second = null,third = null;
for(Tower tower: new Tower[]{a,b,c}){
if(tower.name == "a"||tower.name =="A")
first = tower;
else if(tower.name == "b"||tower.name =="B")
second = tower;
else if(tower.name == "c"||tower.name =="C")
third = tower;
}
System.out.println(first.toString()+";"+second.toString()+";"+third.toString());
}else{
move(num-1,a,c,b,count);
move(1,a,b,c,count);
move(num-1,b,a,c,count);
}
}
public static void printIF(int[] count,int n,Tower from,Tower to,Tower a,Tower b,Tower c){
if(count[0] == 0){
System.out.println("初始状态:"+count[0]);
}
else if(count[0] > 0){
System.out.println(count[0]);
}
if(n != -1&&from != null&&to != null){
System.out.println("将"+n+" "+ "从"+from.name+"柱 移动到"+to.name+ "柱");
}
System.out.println("A柱:["+a.toString()+"]");
System.out.println("B柱:["+b.toString()+"]");
System.out.println("C柱:["+c.toString()+"]");
}
网友评论