HDU 2546 0 1揹包問題

2022-08-18 20:45:19 字數 1628 閱讀 4767

揹包問題是乙個經典的動態規劃模型。它既簡單形象容易理解,又在某種程度上能夠揭示動態規劃的本質,故不少教材都把它作為動態規劃部分的第一道例題。

01揹包問題,可以這麼理解。

題目有n件物品和乙個容量為v的揹包。第i件物品的費用是c[i],價值是w[i]。求解將哪些物品裝入揹包可使價值總和最大。

基本思路

這是最基礎的揹包問題,特點是:每種物品僅有一件,可以選擇放或不放。

用子問題定義狀態:即f[i][v]表示前i件物品恰放入乙個容量為v的揹包可以獲得的最大價值。則其狀態轉移方程便是:

f[i][v]=max

這 個方程非常重要,基本上所有跟揹包相關的問題的方程都是由它衍生出來的。所以有必要將它詳細解釋一下:「將前i件物品放入容量為v的揹包中」這個子問題, 若只考慮第i件物品的策略(放或不放),那麼就可以轉化為乙個只牽扯前i-1件物品的問題。如果不放第i件物品,那麼問題就轉化為「前i-1件物 品放入容量為v的揹包中」,價值為f[i-1][v];如果放第i件物品,那麼問題就轉化為「前i-1件物品放入剩下的容量為v-c[i]的揹包中」,此 時能獲得的最大價值就是f[i-1][v-c[i]]再加上通過放入第i件物品獲得的價值w[i]。

優化空間複雜度

以上方法的時間和空間複雜度均為o(vn),其中時間複雜度應該已經不能再優化了,但空間複雜度卻可以優化到o。

先 考慮上面講的基本思路如何實現,肯定是有乙個主迴圈i=1..n,每次算出來二維陣列f[i][0..v]的所有值。那麼,如果只用乙個陣列 f[0..v],能不能保證第i次迴圈結束後f[v]中表示的就是我們定義的狀態f[i][v]呢?f[i][v]是由f[i-1][v]和f[i-1] [v-c[i]]兩個子問題遞推而來,能否保證在推f[i][v]時(也即在第i次主迴圈中推f[v]時)能夠得到f[i-1][v]和f[i-1] [v-c[i]]的值呢?事實上,這要求在每次主迴圈中我們以v=v..0的順序推f[v],這樣才能保證推f[v]時f[v-c[i]]儲存的是狀態 f[i-1][v-c[i]]的值。偽**如下:

for i=1..n
for v=v..0
f[v]=max;
其中的f[v]=max一句恰就相當於我們的轉移方程

f[i][v]=max

,因為現在的f[v-c[i]]就相當於原來的f[i-1][v-c[i]]。如果將v的迴圈順序從上面的逆序改成順序的話,那麼則成了f[i][v]由f[i][v-c[i]]推知,與本題意不符,但它卻是另乙個重要的揹包問題p02最簡捷的解決方案,故學習只用一維陣列解01揹包問題是十分必要的。

事實上,使用一維陣列解01揹包的程式在後面會被多次用到,所以這裡抽象出乙個處理一件01揹包中的物品過程,以後的**中直接呼叫不加說明。

1 #include2 #include3 #include

4int

main()

522 scanf("

%d", &m);

23if(m < 5)24

28 v = m - 5;29

for(i = 0; i < n; i++)

3037

}38 printf("

%d\n

",m - p[v] -w[maxz]);39}

40return0;

41 }

hdu 2546 0 1揹包問題

悲催了.這道01揹包的題目我wa 了好多遍,感受還是頗多的.說是01揹包,但是還是有一定的研製條件的。首先當飯卡當中的錢不足5塊的時候是不能消費的,所以就應該是原來的值。這裡就wa 了很多遍啊s。然後變通一下,要使得飯卡當中所剩餘額最小,那麼也就是說最大 的那道菜要在最後買,這樣才能得到最優解,那麼...

飯卡 HDU 2546(01揹包)

電子科大本部食堂的飯卡有一種很詭異的設計,即在購買之前判斷餘額。如果購買乙個商品之前,卡上的剩餘金額大於或等於5元,就一定可以購買成功 即使購買後卡上餘額為負 否則無法購買 即使金額足夠 所以大家都希望盡量使卡上的餘額最少。某天,食堂中有n種菜 每種菜可購買一次。已知每種菜的 以及卡上的餘額,問最少...

hdu2546 01揹包理解

電子科大本部食堂的飯卡有一種很詭異的設計,即在購買之前判斷餘額。如果購買乙個商品之前,卡上的剩餘金額大於或等於5元,就一定可以購買成功 即使購買後卡上餘額為負 否則無法購買 即使金額足夠 所以大家都希望盡量使卡上的餘額最少。某天,食堂中有n種菜 每種菜可購買一次。已知每種菜的 以及卡上的餘額,問最少...