誰もが知っているように、再帰は、有名なフィボナッチ数がこの知識ポイントの典型的な例です。
今日は、より古典的な再帰問題であるハノイの塔とカエルのジャンプステップを見てみましょう。しかし、これは実際には数学の問題です。まず、ハノイの塔を見てみましょう。
ハノイの塔
フランスの数学者エドワードルーカスはかつて古代インドの伝説を書きました。世界の中心にあるベナレスの聖なる寺院(インド北部)では、真ちゅう製のプレートに3本の宝石の針が挿入されています。ヒンドゥー教の主神である梵天が世界を創造したとき、彼は針の1つに大小64個の金貨を身に着けていました。これはいわゆるハノイの塔です。昼夜を問わず、次のルールに従ってこれらの金貨を動かす僧侶が常にいます。一度に1つの金貨のみ、どの針が付いていても、小さな金貨は大きな金貨の上になければなりません。僧侶たちは、梵天が身につけていた針から別の針にすべての金貨を移すと、落雷で世界が一掃され、塔、寺院、衆生がすべて滅びると予測しました。
この伝説は非常に興味深いものです。この伝説によると、64個の金貨があります。しかし、スパンコールが3つしかないのか4つしかないのかについて説明します。ネットマップを見てください。
議論は3つの部分から始めます。ディスカッショントピックの冒頭で、この列の位置は動きに影響を与えないが、特定の列が重要であることを理解してください。
スパンコールが1つしかない場合に何回移動するか見てみましょう。
明らかに、1回だけで十分です。
2つの金貨を見てみましょう。
すべてをCピラーに移動する必要があるので
1:
a:A-> B
2:
b:A-> C
3;
a:B-> C
3つのステップで全体を移動できます。
または、スライスbを移動する場合は、最初にスライスを移動し、スライスbの空のCピラーを残して、スライスaの移動を検討する必要があります。
3つのピースの動きを見てみましょう。
次に、上記の考えに従って、cピースを移動する場合は、最初にaピースとbピースを移動し、Cピラーをcピースに残す必要があります。
この条件を最初に満たす必要が
あり、大きいものを小さいものより上にすることはできません。最初にこのように移動する必要があります。
そして、この外観に満足したいのであれば、まず。
結論として、
最初の一歩
第二段階
3番目のステップ
このように見ると、2つの部分だけを動かした前の議論と同じです。
次に、cスライスをC列に移動します。
こんな感じになりました。もう一度見てみましょう。記事の冒頭で述べたように、列の位置は重要ではありません。位置は変更できますが、特定の列に移動する必要があります。さて、先に2つのスパンコールを動かしに行きましたか?
はっきりと見てください、これは2つのスパンコールを動かすステップのように見えます。次に、上記の手順に従ってください。
書き込みステップを計算してみましょう
最初の部分:
2つのスパンコールをBピラーに移動します。
2番目の部分:
CピースをCピラーに移動します
。3番目の部分:
2つのスパンコールをCピラーに移動します。
要約すると
、2つのスパンコールを移動し、2回移動してから、下のスパンコールをもう一度移動する手順です。合計2 * 3 + 1 == 7回。
4つのスパンコールのステップを見てみましょう。
これらの4つのスパンコールを移動する場合は、下のスパンコールを移動する必要があります
このように見ると、2つの部分があります。
1つ:
dピースをC列に移動します
。2:
3つの金のピースabcをC列に移動します。
上に3つ移動するのと同じように、
第一の目的
第二の目的
第三の目的
それは3つの部分で行うことができます。スリーピース移動方式は2回移動する必要があることがわかります。
それは2 * 7 + 1 == 15回です。
****
などなど
**
N個のスパンコールを移動するときは、最初に
1つ-> N-1個のスパンコールを移動することを検討してください。2->
N番目のスライスを再度移動し、3-
> N-1スライスを目的地に再度移動します。
それは3つのステップに分けることができます。
柱の位置は動きに影響を与えません。
コードを見てください、これは回数を数えるためのコードです。
#include <stdio.h>
int hanoi(int n)
{
if (n >= 2)
return 2 * hanoi(n - 1) + 1;
return 1;
}
int main(void)
{
printf("Problem of Hanoi\n");
printf("please input the number for problem:>\n");
int n;
scanf("%d", &n);
printf("%d",hanoi(n));
return 0;
}
これはコンパイルステップのコードです
#include <stdio.h>
void move(char start,char end,int n)
{
static int count = 0;
count++;
printf("NO.%d step,the %d moves from %c to %c\n", count, n, start, end);
}
void hanoi(int n,char pose1,char pose2,char pose3)
{
if (n == 1)
move(pose1, pose3, 1);//一个是特例,不存在中间位置
else
{
hanoi(n - 1, pose1, pose3, pose2);//对应第一次移动N-1个金片
move(pose1, pose3, n);//对应移动第N个金片
hanoi(n - 1, pose2, pose1, pose3);//最后一次移动N-1个金片
}
}
int main(void)
{
char pose1 = 'A';//起始位置
char pose2 = 'B';//中间位置
char pose3 = 'C';//结束位置
int n;
scanf("%d", &n);
hanoi(n, pose1, pose2, pose3);
return 0;
}
再帰を使用する場合は、段階的に分析するのではなく、機能モジュールとして理解してください。その機能を使用して、終了条件を判別し、同時にこの条件に近づきます。
再帰的な書き込み関数を使用すると、計算を「簡単」に行うことができます。
自分の理解を深めるために、学生のようになり、笑わないでください。
ご不明な点がございましたら、アドバイスをお願いします。