栈和队列(6)--用栈来求解汉诺塔问题②

修改汉诺塔的规则,从左到右或者从右到做必须经过中间,也就是说实际动作只有4个:左到中、中到右、右到中和中到左。现在我们把左中右三个地点抽象成栈,依次记为LS、MS和RS。假设最初所有的塔都在LS上,4个动作其实是将一个栈的栈顶元素弹出然后压入到另一个栈的过程。

例如如果是7层塔,最初所有的塔都在LS上,LS从栈顶到栈底依次是1-7,一个动作能发生的先决条件是不违反小压大的原则。那么,form栈弹出的元素num如果想压入到to栈中,那么num的值必须小于当前to栈的栈顶。还有一个原则为相邻不可逆原则,解释如下:

1.我们把四个动作依次定义为L->M、M->L、M->R、R->M;

2.很明显,L->M和M->L为可逆过程。

3.在这个修改过的汉诺塔游戏中,如果想走出最少的步数,那么两个相邻动作绝不可以是互逆过程。

根据以上两个原则可以退出两个结论:

1.游戏的第一步动作一定是L->M

2.在整个过程中为了不违反以上两个原则,四个动作只有一个合适,另外三个都会违反以上两个原则。

综上所述,每一步只有一个动作达标,那么只要每一步都根据这两个原则来动就行了。

实现代码:

package algorithm_6_2;

import java.util.Stack;

public class algorithm_6_2 {
	public enum Action{
		No, LToM,MToL,MToR,RToM
	}
	static public int hanoiProblem2(int num, String left, String mid, String right){
		Stack<Integer> lS = new Stack<Integer>();
		Stack<Integer> mS = new Stack<Integer>();
		Stack<Integer> rS = new Stack<Integer>();
		lS.push(Integer.MAX_VALUE);
		mS.push(Integer.MAX_VALUE);
		rS.push(Integer.MAX_VALUE);
		for (int i =num; i>0;i--){
			lS.push(i);
		}
		Action[] record = { Action.No };
		int step = 0;
		while(rS.size() != num +1){
			step += fStackToStack(record, Action.MToL, Action.LToM, lS, mS, left, mid);
			step += fStackToStack(record, Action.LToM, Action.MToL, mS, lS, mid, left);
			step += fStackToStack(record, Action.RToM, Action.MToR, mS, rS, mid, right);
			step += fStackToStack(record, Action.MToR, Action.RToM, rS, mS, right, mid);
		}
		return step;
	
	}
	private static int fStackToStack(Action[] record, Action preNoAct, Action nowAct, Stack<Integer> fstack, Stack<Integer> tstack,
			String from, String to) {
		if(record[0] !=preNoAct && fstack.peek() < tstack.peek()){
			tstack.push(fstack.pop());
			System.out.println("Move " + tstack.peek() + " from " + from + " to " + to);
			record[0] = nowAct;
			return 1;
		}
		return 0;
	}
	public static void main(String[] args) {
		String str1 = "left";
		String str2 = "mid";
		String str3 = "right";
		hanoiProblem2(3, str1, str2, str3);
	}
}

结果:

Move 1 from left to mid
Move 1 from mid to right
Move 2 from left to mid
Move 1 from right to mid
Move 1 from mid to left
Move 2 from mid to right
Move 1 from left to mid
Move 1 from mid to right
Move 3 from left to mid
Move 1 from right to mid
Move 1 from mid to left
Move 2 from right to mid
Move 1 from left to mid
Move 1 from mid to right
Move 2 from mid to left
Move 1 from right to mid
Move 1 from mid to left
Move 3 from mid to right
Move 1 from left to mid
Move 1 from mid to right
Move 2 from left to mid
Move 1 from right to mid
Move 1 from mid to left
Move 2 from mid to right
Move 1 from left to mid
Move 1 from mid to right

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值