任務描述
在python函式內部,我們可以去呼叫其他函式。所以如果乙個函式在內部呼叫自身,這個函式我們就稱為遞迴函式。本關我們將以漢諾塔的例子來感受遞迴函式的方法與應用。
漢諾塔問題源於印度乙個古老傳說。相傳大梵天創造世界的時候做了三根金剛石柱子,在一根柱子上從下往上按照大小順序摞著64片**圓盤。大梵天命令婆羅門把圓盤從下面開始按大小順序重新擺放在另一根柱子上。並且規定,任何時候,在小圓盤上都不能放大圓盤,且在三根柱子之間一次只能移動乙個圓盤。問應該如何操作?
本關目標就是通過對漢諾塔問題的**,讓讀者了解並掌握遞迴函式的相關知識。
相關知識
在程式語言中,如果一種計算過程的其中每一步都會用到前一步或前幾步的結果,這個計算過程就可以稱為遞迴的。而用遞迴計算過程定義的函式,則被稱為遞迴函式。遞迴函式應用很廣泛,例如連加、連乘及階乘等問題都可以利用遞迴思想來解決。而漢諾塔問題也是遞迴函式的經典應用。
漢諾塔問題的解決思路:如果我們要思考每一步怎麼移可能會非常複雜,但是可以將問題簡化。我們可以先假設除a
柱最下面的盤子之外,已經成功地將a
柱上面的63個盤子移到了b
柱,這時我們只要再將最下面的盤子由a
柱移動到c
柱即可。
當我們將最大的盤子由a
柱移到c
柱後,b
柱上便是餘下的63
個盤子,a
柱為空。因此現在的目標就變成了將這63
個盤子由b
柱移到c
柱。這個問題和原來的問題完全一樣,只是由a
柱換為了b
柱,規模由64
變為了63
。因此可以採用相同的方法,先將上面的62
個盤子由b
柱移到a
柱,再將最下面的盤子移到c
柱。
以此內推,再以b
柱為輔助,將a
柱上面的62
個圓盤最上面的61
個圓盤移動到b
柱,並將最後一塊圓盤移到c
柱。
我們已經發現規律,我們每次都是以a
或b
中一根柱子為輔助,然後先將除了最下面的圓盤之外的其他圓盤移動到輔助柱子上,再將最底下的圓盤移到c柱子上,不斷重複此過程。
這個反覆移動圓盤的過程就是遞迴,例如我們每次想解決n
個圓盤的移動問題,就要先解決(n-1)
個盤子進行同樣操作的問題。
我們先假設a
柱上只有3
個圓盤,利用python進行程式設計實現圓盤的移動,**如下:
def move(n, a, b, c):
if(n == 1):
print(a,"->",c)
return
move(n-1, a, c, b)
move(1, a, b, c)
move(n-1, b, a, c)
move(3, "a", "b", "c")
函式執行結果:
a -> c
a -> b
c -> b
a -> c
b -> a
b -> c
a -> c
程式分析:
首先我們定義了乙個函式move(n,a,b,c)
,引數n
代表a
柱上的圓盤個數,a
,b
,c
三個柱子的順序代表要將a
柱上的圓盤最終移動到c
柱上,然後b
柱作為中間柱。
我們在遞迴函式中肯定會有終止遞迴的條件,2
到4
行的**就是表示當a
柱上的圓盤個數為1的時,就中止遞迴並返回,因為此時a
柱上面只有乙個圓盤的時候肯定就是直接把圓盤從a
柱移動到c
柱了。
第5
行的**move(n-1, a, c, b)
表示先得把a
柱上的n-1
個圓盤從a
柱移動到b
柱,這時c
柱是中間輔助柱。
第6
行的**move(1, a, b, c)
就是條件n=1
的時候,表示把a
柱上剩下的1
個最大圓盤從a
柱移動到c
柱。
第7
行的**move(n-1, b, a, c)
表示現在n-1
個圓盤轉移到要b
柱上了,還是遞迴呼叫move
函式,將n-1
個圓盤從b
柱移動到c
柱,這時a
柱是中間輔助柱。
最後我們呼叫move
函式將3
個圓盤從a
柱移動到到c
柱,當移動64
個圓盤時,只需要將呼叫函式move(n,a,b,c)
中的n
變為64即可,這個計算量是十分巨大的,也只能交給計算機去解決。
小結:我們通過漢諾塔的例子感受了遞迴函式的基本思路,並嘗試解決了乙個具體問題。遞迴函式的優點是定義清晰,思路簡潔,能夠極大簡化程式設計過程。理論上,所有的遞迴函式都可以用迴圈的方法代替,但迴圈方法的程式設計過程要比遞迴函式複雜很多。
程式設計要求
本關的程式設計任務是補全src/step1/recursive.py
檔案的**,實現相應的功能。具體要求如下:
本關涉及的**檔案src/step1/recursive.py
的**框架如下:
#coding=utf-8
#輸入正整數n
n = int(input())
# 請在此新增**,實現n!
#********** begin *********#
#********** end **********#
測試說明
本關的測試檔案是src/step1/recursive.py
,測試過程如下:
平台自動編譯生成recursive.exe
;
平台執行recursive.exe
,並以標準輸入方式提供測試輸入;
平台獲取recursive.exe
輸出,並將其輸出與預期輸出對比。如果一致則測試通過,否則測試失敗。
以下是平台對src/step1/recursive.py
的樣例測試集:
測試輸入:
5
預期輸出:
120
測試輸入:
6
預期輸出:
720
測試輸入:
7
預期輸出:
5040
測試輸入:
8
預期輸出:
40320
#coding=utf-8
#輸入正整數n
n = int(input())
# 請在此新增**,實現n!
#********** begin *********#
def fact(n):
sum = 0
if(n<1):
sum = 1
else:
sum = n*fact(n-1)
return (sum)
#********** end **********#
print(fact(n))
Python遞迴之漢諾塔
漢諾塔一般有兩種返回結果,一種是計算移動的次數,另一種是列印輸入移動的步驟。假設有a,b,c三個柱子,初始時盤子都在a柱子上,需要借助b做中轉站把所有盤子都移動到c上。1.計算移動的次數 首先定義乙個函式hantower n 用來計算移動的次數。如果n 1,直接從a移動到c,返回結果1 如果n 1,...
遞迴之 漢諾塔
遞迴思想的概念 即將乙個複雜問題分解成一系列小的問題,並且這些小問題都具有相同的情形。此時可運用遞迴的思想來解決更易於理解 但並不一定是效率最高的哦 遞迴演算法有三個關鍵點 1 了解題意是否適用遞迴來解決 2 有明確的終止條件 通常是分解出來的一系列小問題裡最簡單的那種情況 3 隨著遞迴演算法的演進...
遞迴之漢諾塔
漢諾塔 time limit 1000 ms memory limit 65536 kib submit statistic problem description 漢諾塔 又稱河內塔 問題是印度的乙個古老的傳說。開天闢地的神勃拉瑪在乙個廟裡留下了三根金剛石的棒a b和c,a上面套著n個圓的金片,最...