ハノイ塔問題を詳しく解説
問題の紹介と背景
ハノイの塔、ハノイの塔としても知られています。古代インドの伝説に由来する知育玩具です。ブラフマーが世界を創造したとき、ダイヤモンドの柱を 3 つ作りました。1 つの柱には 64 枚の金の円盤が大きさの順に積み重ねられていました。ブラフマーはバラモンに、別の柱の円盤を下から上に大きい順に並べ替えるよう命じました。また、小さな円盤では円盤を拡大することはできず、3本の柱の間で一度に移動できる円盤は1枚だけであると規定されています。
次に、ハノイの塔問題の具体的な考え方を分析していきます!
ハノイ塔が動くイラスト
n=3
ここで、最初に前のを入れたことが理解できます。n-12 つのディスクは柱 C の助けを借りて柱 B に移動され、次に最大のディスクが柱 C に移動され、同じアイデアが実行されます。
n=4
いつn=4、まだ以前のものを最初に置くことができますn-1ディスク(ここでは、つまり最初の3枚のディスク) B ピラーに配置してみて (具体的な操作は後で説明します)、次に最大のディスクを C ピラーに配置します。これを行った後、最大のディスクを固定ディスクとして扱うそして合計額を受け取りましたn=3同様の状況が上の図に示されています。その後の転送も簡単ですn=3同じ。
問題分析とコード実装
最初の n-1 ディスク移動方法
前提: 柱 A に円盤が小さい順に n 個配置されており、柱が 3 本あるので、それぞれ A、B、C とします。
1.nが偶数の場合、A→B→C→Aの順に最小の円盤を移動します。、一度移動します。nが奇数の場合、A→C→B→Aの順に最小の円盤を移動します。、一度移動します;
2. 次に、他の 2 つの柱にある可動ディスクを新しい柱に移動します。つまり、空でない柱のディスクを空の柱に移動し、両方の柱が空でない場合は、小さい方のディスクを移動します。、一度移動します。この手順では移動するディスクを明確に指定しませんが、実行されるアクションは独特です。
3. 1と2の操作を繰り返し、最終的にハノイの塔の移動を完成させます。
手数
注文 | 手数 | 法 |
---|---|---|
1 | 1 | 2^1-1 |
2 | 3 | 2^2–1 |
3 | 7 | 2^3-1 |
4 | 15 | 2^4-1 |
… | … | … |
n | \ | 2^n-1 |
その前に引っ越しするならn-1上記の結論によればHanoi(n-1)
、n 個のディスクの移動回数はHanoi(n)=2*Hanoi(n-1)-1
(n>0) を使用して計算できます。
ソースコード
int Hanoi(int n)
{
if (n > 0)
return 2 * Hanoi(n - 1);
else
return 1;
}
int main()
{
int n = 0;
printf("圆盘的个数:>");
scanf("%d", &n);
int ret = Hanoi(n) - 1;
printf("%d\n", ret);
return 0;
}
モバイルステップ印刷
移動ステップをコードで出力するには、プロセス全体を理解する必要があります。実際、ハノイ塔の運動にはループがあります。n が偶数の場合、常に A->B、A->C、B->C、A->B、C->A、C->B でループし、n が奇数の場合は常にループします。 A ->C、A->B、C->B、A->C、B->A、B->C ループでループします。
具体的なコード実装は以下の通りです
#include<stdio.h>
#include<windows.h>
int count;
void Move(int n, char a, char b)
{
count++;
Sleep(1000);
printf("第%2d次移动 Move %d: %c -> %c \n", count, n, a, b);
}
void Hanoi(int n, char a, char b, char c)
{
if (n == 1)
{
Move(n, a, c);
}
else
{
Hanoi(n - 1, a, c, b);
Move(n, a, c);
Hanoi(n - 1, b, a, c);
}
}
int main()
{
int n = 0;
printf("汉诺塔的层数:>");
scanf(" %d", &n);
Hanoi(n, 'A', 'B', 'C');
return 0;
}