對漢諾塔 遞迴問題的新理解

2021-08-14 23:23:13 字數 1655 閱讀 1581

開始學c++函式是看到漢諾塔問題覺得好難理解, 當時記了記**, 了解了些原理就跳過了.昨天時隔許久重新寫漢諾塔, 錯誤百出. 查閱資料, 在現有的知識基礎上有了更多更深的理解.

這次對漢諾塔問題的過程以及對應**有了明確認識

遞迴或者說遞推有了進一步認識

寫這篇部落格除了加深相關認識和記錄之外, 還有對以前的糾錯和反思

知乎上有很多關於漢諾塔問題的理解, 有的非常形象和詳細

漢諾塔遞迴的精髓:

捨棄對全部過程的推導, 而侷限於兩步之間的關係!

其實這也是理解所有遞迴問題的關鍵.

那麼現在的我是如何理解漢諾塔的呢?

我們知道漢諾塔移動次數是乙個遞推公式

fn = 2*fn-1 + 1

fn = 2^n - 1

根據上面的公式

關於fn過程我們可以理解為進行兩個fn-1過程, 再加一

為什麼這麼做?

假設我們要從a到c移動n個盤子, 那麼中間某個過程必然存在1~n-1個盤子在b處, 第n個盤子在a處, 移動一次把它從a移動到c, 然後把n-1個盤子從b全部移動到c

我們可以解析出三個過程:

把1~n-1盤子從a移動到b, 此時以c為中轉, 移動次數為fn-1

把第n個盤子從a移動到c, 移動次數為1

把1~n-1盤子從b移動到c, 此時以a為中轉, 移動次數為fn-1

值得注意的是, n個盤子從第一處處移動到第二處, 中轉為第三處, 這個過程和第一處第二處第三處是a還是b或c是無關的. 和第n+1個盤子也無關, 所以, 可以形象地理解為, 移動了n個盤子, 突然原先的地方又冒出乙個盤子, 然後移動這個盤子, 再把之前的n個盤子進行移動.

c++**為:

#include 

using namespace std;

void hanoi(int n, char

from, char buffer, char to)

else

}int main()

對此**中hanoi函式的理解尤其重要, 在裡面n != 1時呼叫了三次hanoi, 即三次遞迴, 分別代表上面說明的三個過程.

函式的引數變化是移動過程中中轉位置的變化.

如: hanoi(n - 1, from, to, buffer);中, 中轉位置是to

這段**是標準的漢諾塔問題求解方法

下面是我之前的漢諾塔**:

#include 

using

namespace

std;

void hanoi(int n, char a, char b, char c)

hanoi(n-1, a, c, b);

cout

<< a << " -------> "

<< c << endl;

hanoi(n-1, b, a, c);

}int main()

可以看到我當時並不十分理解這個過程, 只是記憶了在這個**中應該怎麼寫, 而這麼寫雖然是正確的, 但對漢諾塔移動的過程沒有很清楚的描述.

遞迴 新漢諾塔

時間限制 1 sec 記憶體限制 128 mb 題目描述 設有n個大小不等的中空圓盤,按從小到大的順序從1到n編號。將這n個圓盤任意的 迭套在三根立柱上,立柱的編號分別為a b c,這個狀態稱為初始狀態。現在要求找到一種步數最少的移動方案,使得從初始狀態轉變為目標狀態。移動時有如下要求 一次只能移乙...

漢諾塔問題(遞迴)

題目描述 對於傳統的漢諾塔遊戲我們做乙個拓展,我們有從大到小放置的n個圓盤,開始時所有圓盤都放在左邊的柱子上,按照漢諾塔遊戲的要求我們要把所有的圓盤都移到右邊的柱子上,請實現乙個函式列印最優移動軌跡。給定乙個int n,表示有n個圓盤。請返回乙個string陣列,其中的元素依次為每次移動的描述。描述...

漢諾塔問題(遞迴)

問題 漢諾塔問題 解法 遞迴求解 思路 先把n 1從a移動b 在把第n個從a移到c 使用遞迴使得 變得簡單 複雜度 2的n次方 1 includeint step 1 void hanoi int level,char a,char b,char c 1 當盤子數大於1時,先把n 1個從a借助c移動...