1. 程式人生 > >ACM入門演算法之---遞迴專場

ACM入門演算法之---遞迴專場

遞迴演算法就是在函式或子過程的內部,直接或者間接地呼叫自己的演算法,在ACM中它是一個入門級的演算法,題目一般非常簡單。它一般解決三類問題:

(1) 資料的定義是按遞迴定義的。(Fibonacci函式)

(2) 問題解法按遞迴演算法實現。(回溯)

(3) 資料的結構形式是按遞迴定義的。(樹的遍歷,圖的搜尋)

遞迴演算法解決問題的特點:

(1) 遞迴就是在過程或函式裡呼叫自身。

(2) 在使用遞迴策略時,必須有一個明確的遞迴結束條件,稱為遞迴出口。

(3) 遞迴演算法解題通常顯得很簡潔,但遞迴演算法解題的執行效率較低,並且在遞迴呼叫的過程當中系統為每一層的返回點、區域性量等開闢了棧來儲存。遞迴次數過多容易造成棧溢位等。所以一般不提倡用遞迴演算法設計程式

遞迴是非常工具性的演算法,常用於其他演算法的實現,例如遞迴常與分治演算法一同出現,也在深搜,遞迴建樹,樹的遞迴遍歷等等地方使用,在很多的模擬題中也有很大的作用,往往使得程式碼變得十分清晰和精短。

   同時ACM中遞迴的題目也相對簡單以下是我做過的一些簡單題的總結。

  下面HDOJ 2044 到 HDOJ 2050是很好的入門級別的遞迴練習,當然,有的題還是很有難度。 

You has solved this problem :-) 2044 36.87%(8238/22344)
HDOJ 2044 

         解題思路:1)每到一個點的路徑數肯定等於它左邊和左下方(左上方)的路徑之和。
              2
)設從a走到b之間一共走n步,則有:


                  dp[n]=dp[n-1]+dp[n-2]; dp[n-1]=dp[n-2]+dp[n-3]..............

貼下程式碼:

#include <iostream>
#include <cstdio>
#include <cmath> 
using namespace std;
long long a[55];
int T,n,m;
int main()
{    
    a[0]=0;
    a[1]=1;
    a[2]=2;
    for (int i=3; i<=50; i++)
    {
        a[i]=a[i-1]+a[i-2];
    }
    cin >> T;
    while (T--)
    {
        cin >> n >> m;
        cout << a[m-n] << endl;
    }
    return 0;
}
HDOJ 2045/2046/2047/2048/2049差不多都是一樣的思想,大家就慢慢推理吧。

       重點說說   HDOJ2050:

解題思路:主要是用到遞推即可。遞推過程:首先分析直線分平面最多多少份: f(1)=2;f(2)=4;f(3)=7;f(4)=11……可知f(n)=f(n-1)+n且f(1)=2.可知f(n)=(1+n)*n/2+1;同理,可將每個折線看成是兩條直線,但是少了一半。因此每一條折線比兩條直線分割的面的部分少2。因此n條折線比2n條直線分割平面形成的部分少2n。所以f(n)=2*n^2-n+1;CP的程式碼:
#include<iostream>  
using namespace std;  
int main()  
{  
    int n;  
    cin>>n;  
    while(n)  
    {  
        int m;  
        cin>>m;  
        int sum=2*m*m-m+1;  
        cout<<sum<<endl;  
        n--;  
    }  
    return 0;  
}