`

The Tower of Hanoi

 
阅读更多

The Tower of Hanoi

 

In the Tower of Hanoi puzzle:

  • There are three stacks (towers), numbered 0, 1, 2.

     

  • There are N disks numbered 0, ..., N-1
         => 0 is the smallest.
  • Initially, the disks are placed in tower 0, in the order largest to smallest. 
         => Smallest on top.
  • Goal: to move the disks to tower 1 using only legal moves.
  • What's a legal move?
    • You can move only a disk at the top of a tower.
    • You can move only one disk at a time.
    • You cannot place a disk on top of a smaller one.
We will solve the problem using (of course) recursion:
  • There are three key steps in the recursion:

     

    • Step 1: move disks 0, ..., N-2 from tower 0 to tower 2 
           => Sub problem of smaller size.

       

    • Step 2: move disk N-1 from tower 0 to tower 1.

       

    • Step 3: move disks 0, ..., N-2 from tower 2 to tower 1. 
           => Sub problem of smaller size.

       

  • In pseudocode (without base case):
         Algorithm towerOfHanoi (n, i, j)
         Input: Disks numbered 0, ..., n are to be moved from tower i to tower j
    
         1.    // ... base case ...
    
               // First find the third tower, other than i and j:
         2.    k = otherTower (i, j)
    
               // Step 1: move disks 0,..,n-1 from i to k
         3.    towerOfHanoi (n-1, i, k)
               // Step 2: move disk# n from i to j
         4.    move (n, i, j)
               // Step 3: move disks 0,...,n-1 from k to j
         5.    towerOfHanoi (n-1, k, j)
         
  • The base case: move a single disk

Here's the program: (source file)

public class TowerOfHanoi {

	public static void main(String[] argv) {
		// A 3-disk puzzle:
		System.out.println("3-Disk solution: ");
		solveHanoi(2, 0, 1);

		// A 4-disk puzzle:
		System.out.println("4-Disk solution: ");
		solveHanoi(3, 0, 1);
	}

	static void solveHanoi(int n, int i, int j) {
		// Bottom-out.
		if (n == 0) {
			// The smallest disk.
			move(0, i, j);
			return;
		}

		int k = other(i, j);
		solveHanoi(n - 1, i, k); // Step 1.
		move(n, i, j); // Step 2.
		solveHanoi(n - 1, k, j); // Step 3.
	}

	static void move(int n, int i, int j) {
		// For now, we'll merely print out the move.
		System.out.println("=> Move disk# " + n + " from tower " + i
				+ " to tower " + j);
	}

	static int other(int i, int j) {
		// return 3-i-j; // this is simpler.
		// Given two towers, return the third.
		if ((i == 0) && (j == 1)) {
			return 2;
		} else if ((i == 1) && (j == 0)) {
			return 2;
		} else if ((i == 1) && (j == 2)) {
			return 0;
		} else if ((i == 2) && (j == 1)) {
			return 0;
		} else if ((i == 0) && (j == 2)) {
			return 1;
		} else if ((i == 2) && (j == 0)) {
			return 1;
		}
		// We shouldn't reach here.
		return -1;
	}
}

 

Note:

  • The above program merely prints out the moves needed 
         => We don't actually maintain the state of each tower.

Next, suppose we want to maintain the state of each tower:

  • The ideal data structure is a stack.
  • We'll use one stack for each tower.

Here's the program: (source file)

import java.util.*;

public class TowerOfHanoi2 {
	// towers[0], towers[1] and towers[2] are the three stacks.
	static Stack<Integer>[] towers;

	public static void main(String[] argv) {
		// A 3-disk puzzle:
		System.out.println("3-Disk solution: ");
		solveHanoi(2, 0, 1);

		// A 4-disk puzzle:
		System.out.println("4-Disk solution: ");
		solveHanoi(3, 0, 1);
	}

	static void solveHanoi(int n, int i, int j) {
		// Create the three stacks.
		towers = new Stack[3];
		for (int k = 0; k < 3; k++) {
			towers[k] = new Stack<Integer>();
		}

		// Put disks 0,...,n on stack 0.
		for (int k = n; k >= 0; k--) {
			towers[0].add(k);
		}

		// Print the initial stack.
		printTowers();

		// Now solve recursively. Note: this is the method below.
		solveHanoiRecursive(n, i, j);
	}

	static void solveHanoiRecursive(int n, int i, int j) {
		// Bottom-out.
		if (n == 0) {
			move(0, i, j);
			return;
		}
		int k = other(i, j);
		solveHanoiRecursive(n - 1, i, k); // Step 1.
		move(n, i, j); // Step 2.
		solveHanoiRecursive(n - 1, k, j); // Step 3.
	}

	static void move(int n, int i, int j) {
		// Pull out the top disk on stack i.
		int topVal = towers[i].pop();
		// Put it on stack j.
		towers[j].push(topVal);
		// Print status.
		System.out.println("Towers after moving " + n + " from tower " + i
				+ " to tower " + j);
		printTowers();
	}

	static int other(int i, int j) {
		return 3-i-j;
	}

	static void printTowers() {
		for (int i = 0; i < towers.length; i++) {
			System.out.print("Tower " + i + ": ");
			if (!towers[i].isEmpty()) {
				for (Integer I : towers[i]) {
					System.out.print(" " + I);
				}
			}
			System.out.println();
		}
	}
}

 

From: http://www.seas.gwu.edu/~drum/cs1112/lectures/module9/module9.html

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics