程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 遞歸討論(二)續,遞歸討論

遞歸討論(二)續,遞歸討論

編輯:C++入門知識

遞歸討論(二)續,遞歸討論


在討論二中,展示了鋼條分段的方法,只不過解題的方法采用的是自頂而下的策略。

個人理解的自頂而下的策略:

首先我們不知道一個大問題的答案,但我們可以將問題規模縮小,外加上已知的一部分。進而變成求解這個小規模問題答案的過程,利用遞歸原理,層層向下,最終回到一個最簡單的問題。

這種處理問題的方式,難免會有重復求解的情況出現。上篇中也有提到!!!

先還是把上篇的部分代碼搞過來看看。

int get_max(int* price,int* len,int num,int *p)//新增的這個指針p指向一個記錄數組,下標為長度num-1,我們用來記錄對應長度num下的最大收益
{
    int result=0;
    if(num>=1&&p[num-1]>=0)    //此處判斷就起到從記錄表中查值作用。
        return p[num-1];
    if(num == 0)//由標記A處的num-len[i]以及其上的if判斷,可以看出下次調用get_max時,可能出現num為0的情況
        return 0;
    for(int i=1;i<=6;i++)
    {
        if(num >=len[ i-1])
        {
            result =  std::max(result,get_max(price,len,num-len[i-1],p)+price[i-1]);//標記A處
        }
    }
    p[num-1] = result;
    return result;
}

 

從代碼中,我們可以粗略計算下,總共調用了多少次get_max();首先在不斷的調用中,get_max()函數中的num值取遍了0-num,權且計作num次

在每次調用中,我們都需要for()循環下,(因為粗略計算嘛)我們就不考慮其中的if判斷了。

最終我們計算出的調用次數:num*6,很類似雙層循環啊

看num值從0變化到num的最大值

價格從1到6變化,嵌套在num的每次變化,顯然是雙層循環了。

我們再分析下:

上述程序中,每次調用的get(..num..),都為了計算當前num的最大收益的吧。只不過大的num根據小的num計算出來,通過遞歸調用實現,但按照程序的實際運行的順序來說,最終還是小num的最大收益先被計算出,然後返回給大的num的使用。這是一種從頂向下,然後結果再層層上返回的過程。

與其這麼麻煩,我們不如先計算小num,然後將小num的值貢獻給比它大的num,這樣就減少了遞歸那樣不斷的調用了。(自下而上的策略)

這樣做的要求就是:我們必須保證num從1到最大時,每個循環都獲得當前num下的最大的收益,先上代碼好了:

void get_max(int* len,int* price,int n,int num,int *p,int* s)//其中n表示可分段種類數  num為鋼條長度,p記錄的當前num下首次截斷的長度,下標為num,s記錄的當前num下最大收益
{
    s[0] = 0;
    for(int i=1;i<=num;i++)
    {
        int q = 0;//當前num下,q用於第二層循環的最大收益的記錄
        for(int j=0;j<n;j++)
        {
            if(i>=len[j])
            {
                s[i] = s[i-len[j]]+price[j];
            }
            if(s[i] > q)//當條件成立時,說明當前num下,最大收益的組合被更新了哦
            {
                q = s[i];
                p[i]=j;
            }
        }
        s[i] = q;

    }
}

這樣我們就獲得最大收益,同時也可以獲得如何分段的方法。

同時一定程度也減少了程序的復雜性。

如果下次再碰到動態規劃問題,就想想這個!理解比較淺薄,望指教!


C語言對於函數的遞歸

你的遞歸程序是錯的,我轉來個對的,帶講解的,你看看。

語言函數的遞歸和調用

一、基本內容:

C語言中的函數可以遞歸調用,即:可以直接(簡單遞歸)或間接(間接遞歸)地自己調自己。

要點:

1、C語言函數可以遞歸調用。

2、可以通過直接或間接兩種方式調用。目前只討論直接遞歸調用。

二、遞歸條件

采用遞歸方法來解決問題,必須符合以下三個條件:

1、可以把要解決的問題轉化為一個新問題,而這個新的問題的解決方法仍與原來的解決方法相同,只是所處理的對象有規律地遞增或遞減。

說明:解決問題的方法相同,調用函數的參數每次不同(有規律的遞增或遞減),如果沒有規律也就不能適用遞歸調用。

2、可以應用這個轉化過程使問題得到解決。

說明:使用其他的辦法比較麻煩或很難解決,而使用遞歸的方法可以很好地解決問題。

3、必定要有一個明確的結束遞歸的條件。

說明:一定要能夠在適當的地方結束遞歸調用。不然可能導致系統崩潰。

三、遞歸實例

例:使用遞歸的方法求n!

當n>1時,求n!的問題可以轉化為n*(n-1)!的新問題。

比如n=5:

第一部分:5*4*3*2*1 n*(n-1)!

第二部分:4*3*2*1 (n-1)*(n-2)!

第三部分:3*2*1 (n-2)(n-3)!

第四部分:2*1 (n-3)(n-4)!

第五部分:1 (n-5)! 5-5=0,得到值1,結束遞歸。

源程序:
fac(int n)
{int t;
if(n==1)||(n==0) return 1;
else
{ t=n*fac(n-1);
return t;
}
}
main( )
{int m,y;
printf(“Enter m:”);
scanf(“%d”,&m);
if(m<0) printf(“Input data Error!\n”);
else
{y=fac(m);
printf(“\n%d! =%d \n”,m,y);
}
}

四、遞歸說明

1、當函數自己調用自己時,系統將自動把函數中當前的變量和形參暫時保留起來,在新一輪的調用過程中,系統為新調用的函數所用到的變量和形參開辟另外的存儲單元(內存空間)。每次調用函數所使用的變量在不同的內存空間。

2、遞歸調用的層次越多,同名變量的占用的存儲單元也就越多。一定要記住......余下全文>>
 

怎分析遞歸的程序

你的問題得你自己解決,我給你個思路
首先,遞歸如果在函數中,我們叫它遞歸函數
比如: f(x)=f(x-1)+f(x-2) 這是 fibonacici數
第二 遞歸一定有邊界!!,請牢記這條,沒邊界就死循環了
比如 f(0)=1; f(1)=1;
如果你看的遞歸程序 不是用函數寫的,那不要緊,關鍵還得找
遞歸變量,比如每次遞歸都會給當前狀態 增加狀態值或狀態轉移,
比如: value=value-1;
if (value==0) { break; }
看遞歸程序 只看兩個
1. 狀態轉移方程 或 狀態轉移表 或者 簡單的狀態轉移函數
2. 邊界條件,退出條件(即 當什麼時候 程序退出 或 遞歸終止)
中間遞歸過程 我們(從來)是不考慮的, 因為遞歸是樹狀的,這個樓主應該知道吧,所以分支太多 考慮不完的。

以上內容原創,
參考資料:以上內容原創,
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved