最近刷了不少題都是在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