前情提要:動態規劃——揹包問題——多重揹包問題
多重揹包問題
有n種物品和乙個容量為v的揹包。第i種物品最多有n[i]件可用,每件費用是c[i],價值是w[i]。
這題目和完全揹包問題很類似,特點是:每種物品都有自己特異的件數、花費、價值。樸素演算法:
每種物品有n[i]件可以取用,需要列舉每種物品選了多少件(列舉件數不能超過揹包容量)
for
(int i=
1;i<=n;i++
)for
(int j=
0;j<=m;j++
)for
(int k=
0;k<=s[i]
&&k*v[i]
<=j;k++
)//與完全揹包相比僅僅是加了乙個判斷條件而已
f[i]
[j]=
max(f[i]
[j],f[i-1]
[j-v[i]
*k]+w[i]
*k);
樸素演算法的時間效率很低,通過下面的二進位制優化可以把遍歷每種物品的n[i]件物品的時間複雜度從o(n)優化為o(log n)
優化:通過展開化簡式子不可行,換用二進位制優化方式
第i種物品是有n[i]件的,這個n[i]可以被展開為n[i]=20+21+…+2k+c (其中2k+1
(20+21+…+2k可以表示區間[ 0,2k+1-1 ]的數,通過加上c這個數,能夠表示區間[0,n[i]]上的所有數)
同時記錄這些加數的值
那這樣的話對於[0,n[i]]的每乙個數,都可以用這些二進位制數表示。即為將n種物品轉化成cnt種物品【每種物品的可選擇數量都是2的某次方(某種物品的最後一種例外)】
完整**如下:
#include
#include
using
namespace std;
const
int n =
24010
, m =
2010
;//陣列開的元素個數n --> 2000*log2000 (log2000約等於11.幾)
int n, m;
int v[n]
, w[n]
;int f[m]
;int
main()
if(s >0)
//加上最後一位c
} n = cnt;
//將n種物品轉化成cnt種物品【每種物品的可選擇數量都是2的某次方(某種物品的最後一種例外)】
for(
int i =
1; i <= n; i ++
)//此處包含0 1揹包問題的優化,可詳見我的揹包專題
for(
int j = m; j >= v[i]
; j --
) f[j]
=max
(f[j]
, f[j - v[i]
]+ w[i]);
cout << f[m]
<< endl;
return0;
}
多重揹包二進位制優化
多重揹包二進位制優化 將價值數量相同的物品分成1,2,4,8.因為100以內任何數都可以由幾個2的n次方數組成。所以,有遍歷沒乙個數變為遍歷每乙個2的n次方數。例題 有n種物品,每種物品的數量為c1,c2.cn。從中任選若干件放在容量為w的揹包裡,每種物品的體積為w1,w2.wn wi為整數 與之相...
多重揹包(二進位制優化)
馬上就要輕院校賽了,沒時間了,下面是網上找的多重揹包,感覺很好 void zeroonepack int cost,int weight,int n void completepack int cost,int weight,int n void multipack int c,int w,int ...
多重揹包二進位制優化
時間長不寫 感覺變菜了。整體優化思路和快速冪很相近 如果第i個物品有num i 個,花費是 c i 價值是 v i 那麼我們可以把它拆分成數個物品。比如某個物品數量是14 花費是cost 價值是value 1 2 4 7 就可以把14個相同物品看成 4 個不同的物品,物品 數量花費 價值第乙個 11...