您的位置:首页 > 其它

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

2016-10-29 23:37 197 查看
修改汉诺塔的规则,从左到右或者从右到做必须经过中间,也就是说实际动作只有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 fro
4000
m 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: