01揹包問題

最近刷了不少題都是在01揹包問題的基礎上改編過來的。今天總結一下。

其實DP和DFS本質上就是一種遍歷,只不過是帶記憶的遍歷罷了

只要用DP能做的用遞歸一定能做,即只要拿到了迭代式就可以用遞歸暴力破解,複雜度一般爲O(2^n)

先回顧一下DP問題的解法: 

 01揹包問題這兩種解法,一種用DP,一種用DFS。

一、DP

 dp[i]代表:從前i個商品中挑選

dp[j]代表:重量不超過j

dp[i][j]代表:價值的最大值

合起來dp[i][j]就代表:前i個商品中挑選重量不超過j的的物品時,價值的最大值

就會有下面的狀態轉移方程和表格:

if j >=w[i]:
     sum_v[i][j] = max{sum_v[i-1][j-w[i]] + v[i], sum_v[i-1][j]}
else:
     sum_v[i][j] = sum_v[i-1][j]

由當前狀態怎麼轉向下一個狀態?

下一個狀態 =Max{當前狀態的Value ,拿下一個物品後的Value}

看這裏:可以發現0-1揹包的狀態轉移方程 dp[i][j] = max{dp[i-1][j-w[i]]+v[i],dp[i-1][j]}的特點,當前狀態僅依賴前一狀態的剩餘體積與當前物品體積v[i]的關係。根據這個特點,我們可以將dp降到一維即dp[j] = max{dp[j],dp[j-w[i]]+v[i]}。從這個方程中我們可以發現,有兩個dp[j],但是要區分開。等號左邊的dp[j]是當前i的狀態,右邊中括號內的dp[j]是第i-1狀態下的值。

所以爲了保證狀態的正確轉移,我們需要先更新等號左邊中的dp[j](當前狀態的dp[j])。

此時數組長度爲揹包容量+1

void FindMaxBetter()//優化空間後的動態規劃
{
    int i,j;
    for(i=1;i<=number;i++)
    {
        for(j=capacity;j>=0;j--)
        {
            if(B[j]<=B[j-w[i]]+v[i] && j-w[i]>=0 )//二維變一維
            {
                B[j]=B[j-w[i]]+v[i];
            }
        }
    }
}

由“下一個狀態 =Max{當前狀態的Value ,拿下一個物品後的Value}”也可以看出是否轉向下一個狀態只跟下一個物品的屬性有關,和揹包的當前容量無關!

可參考上一篇文章的例子加深理解

http://www.cnblogs.com/Christal-R/p/Dynamic_programming.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章