1. 程式人生 > >c++使用樸素遞迴演算法(自頂向下遞迴)和動態規劃dp(帶備忘的自頂向下,自底向上)解決鋼條切割及執行例項結果

c++使用樸素遞迴演算法(自頂向下遞迴)和動態規劃dp(帶備忘的自頂向下,自底向上)解決鋼條切割及執行例項結果

本博文資料來源於演算法導論第三版

動態規劃有兩種等價實現方法:帶備忘的自頂向下發(topDownWithMemoization),自底向上方法,付出額外的記憶體空間來節省計算時間,是典型的時空權衡,遞迴時會儲存每個子問題的解


長度n與對應價格p關係


1~10的對應最優收益


樸素遞迴之自頂向下方法虛擬碼


c++程式碼

#include <iostream>

using namespace std;

upDownCutRod(int p[],int n)
{
    if(n==0)
        return 0;
    int q=-1;
    for(int i=0;i<n;++i)
        q=max(q,p[i]+upDownCutRod(p,n-i-1));
    return q;
}

int main()
{
    int p[10]={1,5,8,9,10,17,17,20,24,30};
    int q=upDownCutRod(p,10);
    cout<<"最優收益值為:"<<q;
    return 0;
}

執行結果


動態規劃自頂向下虛擬碼



c++程式碼實現

#include <iostream>

using namespace std;

int memorizedCutRodAux(int p[],int n,int r[])
{
    int q;//最大收益值
    if(r[n]>=0)
        return r[n];//檢查所需值是否已知
    if(n==0)
        q=0;//n=0時不會有收益
    else
    {
        q=-1;
        for(int i=0;i<n;++i)
            q=max(q,p[i]+memorizedCutRodAux(p,n-i-1,r));
    }
    r[n]=q;
    return q;
}

memorizedCutRod(int p[],int n)
{
    int r[n+1];
    for(int i=0;i<=n;++i)
        r[i]=-1;
    return memorizedCutRodAux(p,n,r);
}

int main()
{
    int p[10]={1,5,8,9,10,17,17,20,24,30};
    int q=memorizedCutRod(p,10);
    cout<<"帶備忘的自頂向下方法的最優收益值為:"<<q;
    return 0;
}

執行結果


自底向上方法虛擬碼


c++程式碼實現

#include <iostream>

using namespace std;

int bottomUpCutRod(int p[],int n)
{
    int r[n+1];//記錄不同規模子問題的解,這裡是1~10
    int q;//記錄收益
    r[0]=0;
    for(int j=1;j<=n;++j)
    {
        q=-1;//初始為負,常見的表示未知數的方法
        for(int i=1;i<=j;++i)
        {
            q=max(q,p[i-1]+r[j-i]);//不再使用遞迴
        }
        r[j]=q;
    }
    return r[n];
}

int main()
{
    int p[10]={1,5,8,9,10,17,17,20,24,30};
    int q=bottomUpCutRod(p,10);
    cout<<"自底向上方法的最優收益值為:"<<q;
    return 0;
}

執行結果