01揹包問題的動態規劃算法

01揹包問題我最初學會的解法是回溯法,第一反應並不是用動態規劃算法去解答。原因是學習動態規劃算法的時候,矩陣連乘、最長公共子串等問題很容易將問題離散化成規模不同的子問題,比較好理解,而對於01揹包問題則不容易想到將揹包容量離散化抽象出子問題,從情感上先入爲主也誤以爲動態規劃算法不是解決01揹包問題的好方法,實際上並不是這樣的。另外,動態規劃算法不對子問題進行重複計算,但是要自底向上將所有子問題都計算一遍,直到計算出最終問題的結果也就是我們要的答案,有點像爬山的感覺。

問題描述:給定n種物品和一揹包,物品i的重量是wi,其價值爲vi,揹包的容量爲C,求能裝入揹包的物品的最大價值。
用m(i,j)表示爲從i到n的物品裝入容量爲j的揹包能產生的最大價值,則能裝入揹包的物品最大價值爲m(1,C)。
遞歸式爲:


上面講到,該問題是對揹包的容量進行離散化,因此時間複雜度是O(nC)。

代碼如下(用的變量名可能和上面有小出入,但是是自描述的):

#include<iostream>
using namespace std;

struct CARGO{
    int weight;
    int value;
};

const int totalWeight=10;
const int totalNumber=5;
CARGO goods[totalNumber]={{2,6},{2,3},{6,5},{5,4},{4,6}};

//1.使用時下標都從1開始;2.遇到複雜結構的初始化用memset方法。
int result[totalNumber+1][totalWeight+1]={0};

int myMax(int i,int j)
{
    return i>=j?i:j;
}

void dp()
{
    int i,j;

    //動態規劃表達式的初始化
    i=totalNumber;
    for(j=1;j<=totalWeight;j++)
    {
        if(goods[i-1].weight>j)//爲保證邏輯完整性,這個if沒刪掉
        {
            result[i][j]=0;
        }
        else
        {
            result[i][j]=goods[i-1].value;
        }
    }

    for(i=totalNumber-1;i>0;i--)
    {
        for(j=1;j<=totalWeight;j++)
        {
            if(goods[i-1].weight>j)
            {
                result[i][j]=result[i+1][j];
            }
            else
            {
                result[i][j]=myMax(result[i+1][j],result[i+1][j-goods[i-1].weight]+goods[i-1].value);
            }
        }
    }
}

int main()
{
    dp();
    cout<<result[1][totalWeight]<<endl;

    //是否理解:完成用result[totalNumber][totalWeight]表示揹包最大value的代碼(從前往後解決子問題的方法)。

    return 0;
}



發佈了34 篇原創文章 · 獲贊 18 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章