用子問題定義狀態:即f[i][v]表示前i件物品恰放入乙個容量為v的揹包可以獲得的最大價值。
1for (int i=1; i<=n; ++i)29
else
101314}
15 }
以上是用二維陣列儲存的,其實還可以用一維陣列儲存進行空間優化(滾動陣列)
從上面計算f[i][j]可以看出,在計算f[i][j]時只使用了f[i-1][0……j],所以說並沒有使用其他子問題,所以說在儲存子問題解的時候,只用儲存f[i-1]的子問題解即可;所以說可以用乙個一維陣列替換掉那個二維陣列,乙個儲存子問題,乙個儲存正在解決的子問題。
我們用f[v]表示當前狀態是容量為v的揹包所得價值
不妨手寫一組資料
揹包容積 8
物品序號 1
體積 4
價值 3
現在我們用正序遍歷一遍
當i = 1時
f[0] = 0 ,f[1] = 0,f[2] = 0,f[3] =0 (顯然當前容積小於該物品的體積,自然就放不進去,統統初始化為0)
f[4] = max( f[4],f[0]+3) 即f[4] = max(0,0+3) = 3;
f[5] = max( f[5],f[1]+3) 即f[5] = max(0,0+3) = 3;
f[6] = max( f[6],f[2]+3) 即f[6] = max(0,0+3) = 3;
f[7] = max( f[7],f[3]+3) 即f[7] = max(0,0+3) = 3;
f[8] = max( f[8],f[4]+3) 即f[8] = max(0,3+3) = 6;
大家快看!!!!!!!!!!!!
有奇怪的事發生了,人群之中竟然鑽出了兩個.....兩個f[4]!!!
那麼問題來了,還記得01揹包的性質麼?這個序號為1的物品竟然用了兩次!!!
相信已經有許多人發現了問題的真相了,不過不懂也不要緊,讓我們來看看逆序遍歷後的結果。
f[8] = max(f[8],f[4]+3)即f[8] = max(0,0+3) = 3;
f[7] = max(f[7],f[3]+3)即f[7] = max(0,0+3) = 3;
f[6] = max(f[6],f[2]+3)即f[8] = max(0,0+3) = 3;
f[5] = max(f[5],f[1]+3)即f[5] = max(0,0+3) = 3;
f[4] = max(f[4],f[0]+3)即f[4] = max(0,0+3) = 3;
f[3] = 0,f[2] = 0,f[1] = 0,f[0] = 0
不知道大家發現沒有,逆序遍歷在向前滾動的時候並沒有對更小體積的清況進行更新,而正序時卻對同一件物品進行了多次操作。
大家請看更新過程
f[4] -> 3
f[4] -> f[8]
我們先更新了f[4](0 -> 3)
卻又用了已經被更新過的f[4] 來更新 沒有更新過的f[8]
就相當於容積為4時已經有了物品1,而在容積為8時卻還要再裝一件物品1,相信如果容積更大,f[4[也會不斷去更新別人,這顯然是違背題意的。
1for(i=1;i<=n;i++)29
}10 }
v的迴圈順序從上面的逆序改成順序的話,那麼則成了f[i][v]由f[i][v-c[i]]推知,與本題意不符,但它卻是另乙個重要的揹包問題p02完全揹包最簡捷的解決方案,因為完全揹包不會記物品的個數,愛裝幾個就裝幾個。
1for (i = 1; i < n; i++)2;
10}11else
///如果放不下
1215}16
}17 }
1for (int i = 1; i <= n; ++i)
27 }
i種物品有n[i]+1種策略:取0件,取1件……取
c 揹包九講之有依賴的揹包問題
一 揹包九講總述 關於動態規劃問題,最典型的就是揹包九講,先理解揹包九講後再總結關於動態規劃的問題。二 有依賴的揹包問題這個問題理解起來挺簡單吧,就是如果買一件物品 附件 就必須買另一件 主件 這裡為了簡化問題,就假設主件不依賴另乙個物品,附件不被另乙個物品依賴,沒有某件物品同時依賴多件物品。不知道...
揹包九講之七(有依賴的揹包問題)
1 2 即物品間存在依賴,比如i依賴於j,表示若選物品i,則必須選物品j 34有很多個箱子,想買箱子中的物品必須先買下箱子,典型的依賴揹包 5將不依賴其他物品的物品稱為主件,依賴其他物品的物品稱為附件 6我們有n個箱子,箱子裡面的物品個數為cnt i 7那麼箱子稱為主件,箱子裡面的物品稱為附件 8那...
揹包九講 01揹包的內迴圈逆序問題
對於01揹包,用二維陣列做dp的情況如下 f i,v 代表,在揹包容量為v的情況下,從前i件物品中選出若干件 因揹包容量的限制,可能不會所有i件都在裡面,取最大值時揹包裡應該是權值相對較大的那些物品 所能得到的最大價值。第一句對dp設定初始條件。兩個for迴圈遍歷所有的情況 i從1 n表示從i件物品...