演算法學習1 遞迴

2021-08-08 16:17:39 字數 4787 閱讀 2820

遞迴: 乙個函式呼叫其自身。不同名字空間上的迴圈。

注意:使用遞迴策略時,必須有乙個明確的遞迴結束條件,否則遞迴將會無限進行下去。

參考

中國大學mooc - 演算法基礎

話歪之地的部落格

int factorial(int n)  else 

}

執行f(3)2 -> f(3)5 -> f(2)2 -> f(2)5 -> f(1)2 -> f(1)5 -> f(0)2 -> f(0)3:返回1 ->

f(1)5:返回1*1 -> f(2)5:返回2*1 -> f(3)5:返回3*2 -> 函式執行結束

實現

通過棧實現

遞迴作用

1. 替代多重迴圈

2. 解決本來就是用遞迴形式定義的問題

3. 將問題分解為規模更小的的子問題進行求解

替代多重迴圈,八皇后問題用多重迴圈求解,n皇后則用遞迴

wiki-西洋棋queen走法

輸入整數n,要求n個西洋棋的皇后,擺在n*n的棋盤上,同一行、同一列、同一斜線上的皇后都會自動攻擊,輸出全部方案。

輸出結果每行代表一種擺法,行裡第i個數字如果是n,就代表第i行皇后放在第n列,皇后的行列編號從1開始

樣例輸入

4樣例輸出

2 1 3 4

3 1 4 2

思路分析(遞迴以及非遞迴思路)

#include 

#include

using

namespace

std;

int n;

int queenpos[100]; // 存算好的皇后位置,最左上角是(0,0)

void nqueen(int k);

int main()

// 在0~k-1行皇后擺好情況下,擺第k行及其以後的皇后

void nqueen(int k)

cout

<< endl;

return ;

} else

if( j==k )

} // for( i=0; i}

}

樹老師爬樓梯,他可以每次走1級或者2級,輸入樓梯的級數,求不同的走法數。

例如:樓梯一共有3級,他可以每次都走一級,或者第一次走一級,第二次走兩級,也可以第一次走兩級,第二次走一級,一共3種方法。

輸入

輸入包含若干行,每行包含乙個正整數n,代表樓梯級數,1 <=n <= 30輸出不同的走法數,每一行輸入對應一行

輸出

不同的走法數,每一行輸入對應一行輸出

樣例輸入

5 8

10樣例輸出

8 34

89思路分析

n級台階的走法 = 先走一級後,n-1級台階的走法 + 先走兩級後,n-2級台階的走法。即 f(n) = f(n-1)+f(n-2)

邊界條件設定可以有多種做法

int main() 把m個同樣的蘋果放在n個同樣的盤子裡,允許有的盤子空著不放,問共有多少種不同的分法?(注:5,1,1和1,5,1 是同一種分法)

輸入

第一行時測試資料的數目t(0<=t<=20),以下兩行均包含兩個整數m和n,其中1<=m,n<=10。

輸出

對輸入的每組資料m,n,用一行輸出相應的放法數k。

樣例輸入

1 7 3

樣例輸出

8分析

設 f(m,n) 為m個相同的蘋果放到n個相同的盤子中的方法總數。

下面對n進行討論,

當 n>m 時,則必有n-m個盤子是空的。去掉這些空盤子對總的擺放情況數目不影響。有 f(m,n) = f(m,m)

當 n<=m 時,所有的情況可以分成兩大類,一類是有空盤的情況,一類是無空盤的情況。

1 有空盤,至少有乙個空盤,這類情況數目 f(m,n-1)

2 無空盤,即所有的盤子至少乙個蘋果。先把每個盤子裡都放乙個蘋果,還剩m-n個蘋果;接下來就是把m-n個蘋果放到n個盤子裡,此類情況放法總數為 f(m-n,n)

綜上

int main()

return

0;

}動態規劃解法

問題延伸 - 整數劃分

把乙個正整數n表示成一系列正整數之和,加數s不超過m。

6 5+1

4+2,4+1+1

3+3,3+2+1,3+1+1+1

2+2+2,2+2+1+1,2+1+1+1+1

1+1+1+1+1+1⎧⎩

⎨⎪⎪⎪

⎪⎪⎪⎪

⎪⎪⎪f

(1,m

)=1,

m>=1f

(n,1

)=1,

n>=1f

(n,m

)=f(

n,n)

,m>=nf

(n,n

)=1+

f(n,

n−1)

f(n,

m)=f

(n,m

−1)+

f(n−

m,m)

,n>

m>1只

有一種劃

分即1個

1只有一

種劃分即

n個1最

大加數m

不能超過

ns=n的劃分

和s<=n-1的劃分

s=m的劃分

和s<=m-1的劃分

給出4個小於10個正整數,你可以使用加減乘除4種運算以及括號把這4個數連線起來得到乙個表示式。現在的問題是,是否存在一種方式使得得到的表示式的結果等於24。

這裡加減乘除以及括號的運算結果和運算的優先順序跟我們平常的定義一致(這裡的除法定義是實數除法)。

比如,對於5,5,5,1,我們知道5 * (5 – 1 / 5) = 24,因此可以得到24。又比如,對於1,1,4,2,我們怎麼都不能得到24。

輸入

輸入資料報括多行,每行給出一組測試資料,包括4個小於10個正整數。最後一組測試資料中包括4個0,表示輸入的結束,這組資料不用處理。

輸出

對於每一組測試資料,輸出一行,如果可以得到24,輸出「yes」;否則,輸出「no」。

樣例輸入

5 5 5 1

1 1 4 2

0 0 0 0

樣例輸出

yes

no分析

n個數算24,必有兩個數要先算。這兩個數算的結果,和剩餘n-2個數,就構成了n-1個數求24的問題

列舉先算的兩個數,以及這兩個數的運算方式。

注意:浮點數比較是否相等,不能用 ==

邊界條件

#include

#include

using namespace std;

double a[5];

#define eps 1e-6 //10^(-6),當浮點數小於這個數可認為是0

bool iszero(double x)

bool count24(double a, int n)

double b[5];

for( int i=0 ; i1; i++ )

b[m] = a[i]+a[j]; //元素b[m]是a[i]和a[j]相加

if( count24(b,m+1) ) return

true;

b[m]=a[i]-a[j]; //元素b[m]是a[i]和a[j]相減

if(count24(b,m+1)) return

true;

b[m]=a[j]-a[i];

if( count24(b,m+1) ) return

true;

b[m]=a[i]*a[j]; //元素b[m]是a[i]和a[j]相乘

if( count24(b,m+1) ) return

true;

if( !iszero(a[j]) )

if( !iszero(a[i]) )

} }

return

false;

} int main()

return

0;

}

#include 

using

namespace

std;

// 將a的盤子以b為中轉移動到c盤

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

}int main()

演算法學習 遞迴1

遞迴演算法是把問題轉化為規模縮小了的同類問題的子問題。然後遞迴呼叫函式 或過程 來表示問題的解。一般來說 能夠用到遞迴解決的問題應該滿足以下三個條件 1 待解決的問題可以轉化為乙個或多個子問題來求解,而這些子問題的求解方法與原問題相同,只是在數量規模上會有所不同 2 遞迴呼叫的次數必須是有限的 3 ...

遞迴 演算法學習

遞迴按照遞迴方式可以分為直接遞迴和間接遞迴 1.直接遞迴 遞迴過程p直接呼叫自己 2.間接遞迴 p包含另乙個過程d,而d又呼叫p 遞迴例項 1.漢諾塔問題 include include void hanoi int n,char a,char b,char c int main void 2.八皇...

遞迴演算法學習

所謂的遞迴函式就是在函式體內呼叫本函式。使用遞迴函式一定要注意,處理不當就會進入死迴圈。遞迴函式只有在特定的情況下使用 比如階乘問題 遞迴演算法測試 10的階乘 function f num else console.log 10 的結果為 f 10 請實現乙個fibonacci函式,要求其引數和返...