Article directory
Using Stack to Solve Hannover Tower Problem
[title]
The Hanoi Tower Problem is a classic one. Here we revise the rules of the game: the restriction can not be moved directly from the left tower to the right, nor from the right to the left, but must go through the middle. When the tower has N layers, print the optimal moving process and the maximum total moving steps.
For example, when the number of towers is two, the top tower is marked 1 and the bottom tower is marked 2, then print:
Move 1 from left to mid Move 1 from mid right Move 2 form 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 It will move steps
[request]
The following two methods are used to solve the problem:
- Method 1: Recursive method
- Method 2: Non-recursive method, using stack to simulate the three towers of Hanoi Tower
[answer]
Method 1: Recursive method
Firstly, if only the top tower needs to be moved, the following treatment will be taken:
- If you want to move from "left" to "middle", print "Move 1 from left to mid".
- If you want to move from "middle" to "left", print "Move 1 from mid to left".
- If you want to move from "middle" to "right", print "Move 1 from mid to right"
- If you want to move from "right" to "middle", print "Move 1 from right to mid"
- If you want to move from "left" to "right", print "Move 1 from left to mid". "Move 1 from mid to right".
- If you want to move from "right" to "left", print "Move 1 from right to mid" and "Move 1 from mid to left".
That's the middle condition of recursion, the printing process when only the upper tower is left.
Next, we analyze the remaining multi-storey towers.
If there are N layers left, the order from top to bottom is 1 to N, then the following judgment can be made:
- If the remaining N-tier towers are "left" and want to move all of them to "middle", there are three steps:
- Transfer the 1-N-1 tower from "left" to "right" first, obviously to the recursive process.
- Move the N-layer tower from "left" to "middle".
- Then move all 1-N-1 towers from "right" to "middle", obviously to the recursive process.
- If all the remaining N-layer towers are moved from "middle" to "left", from "middle" to "right" and from "right" to "middle", the process can be divided into three steps, as in the same way.
- If the remaining towers are on the left, there are five steps to move them all to the right.
- The 1-N-1 tower is first moved from "left" to "right" and is obviously handed over to the recursive process.
- Move the N-layer tower from "left" to "middle".
- All the 1-N-1 towers were moved from "right" to "left" and were obviously handed over to the recursive process.
- Move the N-layer tower from "middle" to "right".
- All the 1-N-1 towers were moved from "left" to "right" and were obviously handed over to the recursive process.
- If all the remaining N layers are on the "right" side, the process of moving them all to the "left" side is the same as that in case 3, which is divided into five parts.
Refer to the following hanoProblem1 method for the code of the above recursive process after logical simplification.
public class HanoiProblem1 { public int hanoiProblem1(int num, String left, String mid, String right) { if (num < 1) { return 0; } return process(num, left, mid, right, left, right); } public int process(int num, String left, String mid, String right, String from, String to) { if (num == 1) { if (from.equals(mid) || to.equals(mid)) { System.out.println("Move 1 from " + from + " to " + to); return 1; } else { System.out.println("Move 1 from " + from + " to " + mid); System.out.println("Move 1 from " + mid + " to " + to); return 2; } } if (from.equals(mid) || to.equals(mid)) { String another = (from.equals(left) || to.equals(left)) ? right : left; int part1 = process(num - 1, left, mid, right, from, another); int part2 = 1; System.out.println("Move " + num + " from " + from + " to " + to); int part3 = process(num - 1, left, mid, right, another, to); return part1 + part2 + part3; } else { int part1 = process(num - 1, left, mid, right, from, to); int part2 = 1; System.out.println("Move " + num + " from " + from + " to " + mid); int part3 = process(num - 1, left, mid, right, to, from); int part4 = 1; System.out.println("Move " + num + " from " + mid + " to " + to); int part5 = process(num - 1, left, mid, right, from, to); return part1 + part2 + part3 + part4 + part5; } } public static void main(String[] args) { HanoiProblem1 test = new HanoiProblem1(); test.hanoiProblem1(3, "left", "mid", "right"); } }
Method 2: Non-recursive method - using stack to simulate the whole process.
The revised Hanoi Tower Problem should not allow any tower to move directly from "left" to "right", nor from "right" to "left", but through the intermediate process. That is to say, there are only four actual actions: "left" to "middle", "middle" to "left", "middle" to "right".
Now we abstract the left, middle and right locations into stacks, which are LS, MS and RS in turn. Initially all the towers were on LS. So the above four actions can be regarded as: one stack pops up the top element of the stack and then pushes it into another stack as the top of the stack.
For example, if it is a 7-storey tower, then initially all the towers are on LS, LS from the top of the stack to the bottom of the stack is 1-7 in turn. If the "left" to "middle" action occurs now, the corresponding operation of LS will pop up the top element 1 of the stack, and then 1 is pushed into the MS stack to become the top of the MS stack. Others are the same.
The precondition for an action to occur does not violate the principle of small pressure.
If num is to be pushed into the to stack, the value of num must be less than the top of the current to stack.
Another principle is not very obvious, but also very important. Teach the principle of irreversibility of adjacency. Explain it as follows:
1. We define the four actions in turn as L->M, M->L, M->R and R->M.
2. Obviously, the processes of L->M and M->L will be inverse, and the processes of M->R and R->M will be inverse.
3. In the modified Hanoi Tower game, if you want to go out of the minimum number of steps, then any two adjacent actions are not inverse process. For example, if the action of the previous step is L - > M, then this step can never be M - > L. The intuitive explanation is: you moved the top of a stack from "left" to "middle" in the previous step. Why did you move back in this step? This is certainly not the way to get the minimum number of steps. Similarly, M - > R action and R - > M action can not occur adjacent to each other.
With the principle of small pressure and large adjacent irreversibility, we can deduce two very useful conclusions: the core of non-recursive method
1. The first action of the game must be L - > M, which is obvious.
2. At any moment in the process of walking out of the minimum number of steps, only one of the four actions does not violate the principle of small pressure and large irreversibility, and the other three actions will violate it.
For conclusion 2, let's give a simple proof.
Because the first action has been determined to be L - > M, there will be the first step in each subsequent step.
Suppose the action of the previous step is L - > M:
- According to the principle of small pressure, the action of L - > M will not happen again.
- According to the principle of proximity and non-neighbourliness, the action of M-> L should not occur either.
- According to the principle of small pressure and large pressure, M - > R and R - > M can only meet one standard.
Suppose the action of the previous step is M - > L:
- According to the principle of small pressure, the action of M - > L will not happen again.
- According to the principle of proximity and non-neighbourliness, the action of L-> M should not occur either.
- According to the principle of small pressure and large pressure, M - > R and R - > M can only meet one standard.
Suppose the action of the previous step is M->R:
- According to the principle of small pressure and large pressure, the action of M - > R will not happen again.
- According to the principle of proximity and non-neighbourliness, the action of R - > M should not occur either.
- According to the principle of small pressure and large pressure, L - > M and M - > L can only meet one standard.
Suppose the action of the previous step is R - > M:
- According to the principle of small pressure, the action of R - > M will not happen again.
- According to the principle of proximity and non-neighbourliness, the action of M->R should not occur either.
- According to the principle of small pressure and large pressure, L - > M and M - > L can only meet one standard.
To sum up, there will only be one action in each step, so as long as all the Eastern European work is inspected according to these two principles without taking a step, which action will go which action meets the standard, anyway, only one action meets the requirement each time, and it is enough to walk down in sequence.
** Refer to the hanol problem 2 method for specific non-recursive processes
public class HanoiProblem2 { 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 0; } return 0; } }