栈与队列5——汉诺塔问题(方案二)

题目

汉诺塔问题的基础上,增加限制,必须得经过中间,不能直接从左到右或从右到左,求当塔有N层的时候打印最优移动过程和最优移动总步数


要求

  1. 法一:递归法
  2. 法二:非递归法,用栈来模拟

解析

法二:非递归法,用栈实现

把左,中,右抽象成栈,分别即为ls,ms,rs,最初所有的块都在ls上,总共只能有四个动作,左到中,中到右,右到中,中到左,因为一次移动必须经过中间。每次都是从一个栈的栈顶弹出然后压入另外一个栈里。

两个原则:1>不能小压大2>相邻不可逆(当前从L->M,下一步不能从M->L)

结论:

  1. 第一步一定是L->M
  2. 在走出最少步数的过程中,四个动作只有一个动作可以满足上面的两个原则。

法二源码

public enum Action{
	No,LtoM,MtoL,MtoR,RtoM
}

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;
}
public 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;
}

这道题有点难,欢迎大家交流讨论~

发布了43 篇原创文章 · 获赞 21 · 访问量 4932

猜你喜欢

转载自blog.csdn.net/flying_1314/article/details/103752477