1. 题目
如下图所示,有三根相邻的柱子,分别标记为A、B、C。柱子A从上到下按金字塔状叠放着n个大小依次递增的盘子,若此时需要把所有的盘子移动到柱子C上,条件是每次只能移动一个盘子,而且所有柱子上都不能出现大盘子落在小盘子上方的情况,请问至少需要移动多少次?
2. 解法
(1)考虑只有一个盘子的情况,此时只需要把柱子A上的盘子移动到柱子C即可,记为“A -> C”。
(2)考虑有两个盘子的情况,此时需要先把柱子A上的小盘子移动到柱子B,记为“A -> B”,再把柱子A上的大盘子移动到柱子C,记为“A -> C”,最后把柱子B上的小盘子移动到柱子C即可,记为“B -> C”。
(3)考虑有两个以上即n个盘子的情况,从中间移动柱子A最下面的盘子这一步开始看,此时柱子A上只有一个最大的盘子,柱子B上依次叠放着n-1个盘子,柱子C上没有盘子。这一步之前的步骤可以看作是把n-1个盘子从柱子A上经柱子C辅助移动到柱子B上的过程,然后这一步直接把柱子A上最大的盘子移动到柱子C即可,这一步之后的步骤可以看作是把n-1个盘子从柱子B上经柱子A辅助移动到柱子C上的过程。
(4)对比步骤(2)和(3),可以看出这是一个递归移动的过程,现在利用一个移动方法来显示盘子移动的轨迹,方法的参数分别是盘子的个数、柱子A、柱子B、柱子C。
3. 代码
using System;
namespace _03
{
class Program
{
public static int count;
static void Main(string[] args)
{
while (true)
{
count = 0;
Console.WriteLine("请输入盘子的个数:");
Hanoi(int.Parse(Console.ReadLine()), "A", "B", "C");
Console.WriteLine($"至少需要移动{count}次!");
Console.WriteLine("是否继续(y/n)?");
if (Console.ReadLine().Contains("n"))
{
break;
}
}
}
public static void Hanoi(int n, string A, string B, string C)
{
if (n == 1)
{
Console.WriteLine($"{A} -> {C}");
count++;
return;
}
Hanoi(n - 1, A, C, B);//A -> B
Hanoi(1, A, B, C);//A -> C
Hanoi(n - 1, B, A, C);//B -> C
}
}
}