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

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

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

 

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

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

#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;
}
相關文章
相關標籤/搜索