UVa10017 - The Never Ending Towers of Hanoi(dfs)

本文详细介绍了Hanoi塔问题的规则,并提供了一个解决该问题的高效算法。通过逐步展示移动磁盘的过程,实现从一个柱子到另一个柱子的完整转移。文章还讨论了最小移动次数和输入输出格式,提供了具体的示例来说明解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The Never Ending Towers of Hanoi

The Problem

In 1883, Edward Lucas invented, or perhaps reinvented, one of the most popular puzzles of all times - the Tower of Hanoi, as he called it - which is still used today in many computer science textbooks to demonstrate how to write a recursive algorithm or program. First of all, we will make a list of the rules of the puzzle:

· There are three pegs: A, B and C. 
· There are n disks. The number n is constant while working the puzzle. 
· All disks are different in size. 
· The disks are initially stacked on peg A so that they increase in size from the top to the bottom. 
· The goal of the puzzle is to transfer the entire tower from the A peg to the peg C. 
· One disk at a time can be moved from the top of a stack either to an empty peg or to a peg with a larger disk than itself on the top of its stack.

Your job will be to write a program which will show a copy of the puzzle on the screen step by step, as you move the disks around. This program has to solve the problem in an efficient way.

TIP: It is well known and rather easy to prove that the minimum number of moves needed to complete the puzzle with n disks is  2n -1. 
 

The Input

The input file will consist of a series of lines. Each line will contain two integers n, m. n, lying within the range [1,250], will denote the number of disks and m, belonging to [0,2n-1], will be the number of the last move, you may assume that m will also be less than 216, and you may also assume that a good algorithm will always have enough time. The file will end at a line formed by two zeros.

The Output

The output will consist again of a series of lines, formatted as show below. 
NOTES: There are 3 spaces between de ‘=>’ and the first number printed. If there isn't any number, there should be no spaces. 
               All the disks in a single peg are printed in a single line.
Print a blank line after every problem.

Sample Input

64 2 
8 45 
0 0

Sample Output

Problem #1

A=>   64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
B=>
C=>

A=>   64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2
B=>   1
C=>

A=>   64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3
B=>   1
C=>   2

Problem #2

A=>   8 7 6 5 4 3 2 1
B=>
C=>

A=>   8 7 6 5 4 3 2
B=>   1
C=>

A=>   8 7 6 5 4 3
B=>   1
C=>   2

A=>   8 7 6 5 4 3
B=>
C=>   2 1

A=>   8 7 6 5 4
B=>   3
C=>   2 1

A=>   8 7 6 5 4 1
B=>   3
C=>   2

A=>   8 7 6 5 4 1
B=>   3 2
C=>

A=>   8 7 6 5 4
B=>   3 2 1
C=>

A=>   8 7 6 5
B=>   3 2 1
C=>   4

A=>   8 7 6 5
B=>   3 2
C=>   4 1

A=>   8 7 6 5 2
B=>   3
C=>   4 1

A=>   8 7 6 5 2 1
B=>   3
C=>   4

A=>   8 7 6 5 2 1
B=>
C=>   4 3

A=>   8 7 6 5 2
B=>   1
C=>   4 3

A=>   8 7 6 5
B=>   1
C=>   4 3 2

A=>   8 7 6 5
B=>
C=>   4 3 2 1

A=>   8 7 6
B=>   5
C=>   4 3 2 1

A=>   8 7 6 1
B=>   5
C=>   4 3 2

A=>   8 7 6 1
B=>   5 2
C=>   4 3

A=>   8 7 6
B=>   5 2 1
C=>   4 3

A=>   8 7 6 3
B=>   5 2 1
C=>   4

A=>   8 7 6 3
B=>   5 2
C=>   4 1

A=>   8 7 6 3 2
B=>   5
C=>   4 1

A=>   8 7 6 3 2 1
B=>   5
C=>   4

A=>   8 7 6 3 2 1
B=>   5 4
C=>

A=>   8 7 6 3 2
B=>   5 4 1
C=>

A=>   8 7 6 3
B=>   5 4 1
C=>   2

A=>   8 7 6 3
B=>   5 4
C=>   2 1

A=>   8 7 6
B=>   5 4 3
C=>   2 1

A=>   8 7 6 1
B=>   5 4 3
C=>   2

A=>   8 7 6 1
B=>   5 4 3 2
C=>

A=>   8 7 6
B=>   5 4 3 2 1
C=>

A=>   8 7
B=>   5 4 3 2 1
C=>   6

A=>   8 7
B=>   5 4 3 2
C=>   6 1

A=>   8 7 2
B=>   5 4 3
C=>   6 1

A=>   8 7 2 1
B=>   5 4 3
C=>   6

A=>   8 7 2 1
B=>   5 4
C=>   6 3

A=>   8 7 2
B=>   5 4 1
C=>   6 3

A=>   8 7
B=>   5 4 1
C=>   6 3 2

A=>   8 7
B=>   5 4
C=>   6 3 2 1

A=>   8 7 4
B=>   5
C=>   6 3 2 1

A=>   8 7 4 1
B=>   5
C=>   6 3 2

A=>   8 7 4 1
B=>   5 2
C=>   6 3

A=>   8 7 4
B=>   5 2 1
C=>   6 3

A=>   8 7 4 3
B=>   5 2 1
C=>   6

A=>   8 7 4 3
B=>   5 2
C=>   6 1

import java.io.FileInputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.OutputStreamWriter;
import java.io.StreamTokenizer;

public class Main {
	private static final boolean DEBUG = false;
	private static final int N = 260;
	private BufferedReader cin;
	private PrintWriter cout;
	private StreamTokenizer tokenizer;
	private int n, m;
	private int[][] pegs;
	private int[] size;
	private int cnt;
	private int cas = 1;
	
	public void init() 
	{
		try {
			if (DEBUG) {
				cin = new BufferedReader(new InputStreamReader(
						new FileInputStream("e:\\uva_in.txt")));
			} else {
				cin = new BufferedReader(new InputStreamReader(System.in));
			}

			tokenizer = new StreamTokenizer(cin);
			
			cout = new PrintWriter(new OutputStreamWriter(System.out));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private String next() 
	{
		try {
			 tokenizer.nextToken(); 
			 if (tokenizer.ttype == StreamTokenizer.TT_EOF) return null; 
			 else if (tokenizer.ttype == StreamTokenizer.TT_NUMBER) { 
			 	return String.valueOf((int)tokenizer.nval); 
			} else return tokenizer.sval;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public boolean input() 
	{
		n = Integer.parseInt(next());
		m = Integer.parseInt(next());

		if (n == 0 && m == 0) return false;

		pegs = new int[3][n];
		size = new int[3];
		size[0] = n;
		size[1] = size[2] = 0;

		for (int i = 0; i < size[0]; i++) {
			pegs[0][i] = n - i;
		}
		
		return true;
	}

	private void dfs(int n, int a, int b, int c)
	{
		if (n == 0) return;
		if (cnt >= m) return;
		
		dfs(n - 1, a, c, b);
		if (cnt >= m) return;
		pegs[c][size[c]] = pegs[a][size[a] - 1];
		size[c]++;
		size[a]--;
		for (int i = 0;  i < 3; i++) {
			int len = size[i];
			cout.print((char)('A' + i) + "=>");

			for (int j = 0; j < len; j++) {
				if (j == 0) cout.print("   ");
				else cout.print(" ");
				cout.print(pegs[i][j]);
			}
			cout.println();
		}
		cout.println();
		cout.flush();
		if (cnt++ == m) return;
		dfs(n - 1, b, a, c);
		
	}
	
	public void solve() 
	{
		cnt = 0;
		cout.println("Problem #" + cas++);
		cout.println();
		for (int i = 0; i < 3; i++) {
			int len = size[i];
			cout.print((char)('A' + i) + "=>");
			for (int j = 0; j < len; j++) {
				if (j == 0) cout.print("   ");
				else cout.print(" ");
				cout.print( pegs[i][j]);
			}
			cout.println();
		}
		cout.println();
		dfs(n, 0, 1, 2);
	}
	
	public static void main(String[] args) 
	{
		Main solver = new Main();
		solver.init();
		
		while (solver.input()) {
			solver.solve();
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kgduu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值