hdu2844 Coins(普通的多重背包 + 二进制优化)
看完背包九講的多重背包之后,這題目應(yīng)該可以輕松做出來了
模型:
有N種物品和一個(gè)容量為V的背包。第i種物品最多有n[i]件可用,每件費(fèi)用是c[i],價(jià)值是w[i]。求解將哪些物品裝入背包可使這些物品的費(fèi)用總和不超過背包容量,且價(jià)值總和最大。
方法:
基本算法
這題目和完全背包問題很類似。基本的方程只需將完全背包問題的方程略微一改即可,因?yàn)閷?duì)于第i種物品有n[i]+1種策略:取0件,取1件……取n[i]件。令f[i][v]表示前i種物品恰放入一個(gè)容量為v的背包的最大權(quán)值,則有狀態(tài)轉(zhuǎn)移方程:
f[i][v]=max{f[i-1][v-k*c[i]]+k*w[i]|0<=k<=n[i]}
復(fù)雜度是O(V*Σn[i])。
轉(zhuǎn)化為01背包問題
另一種好想好寫的基本方法是轉(zhuǎn)化為01背包求解:把第i種物品換成n[i]件01背包中的物品,則得到了物品數(shù)為Σn[i]的01背包問題,直接求解,復(fù)雜度仍然是O(V*Σn[i])。
但是我們期望將它轉(zhuǎn)化為01背包問題之后能夠像完全背包一樣降低復(fù)雜度。仍然考慮二進(jìn)制的思想,我們考慮把第i種物品換成若干件物品,使得原問題中第i種物品可取的每種策略——取0..n[i]件——均能等價(jià)于取若干件代換以后的物品。另外,取超過n[i]件的策略必不能出現(xiàn)。
方法是:將第i種物品分成若干件物品,其中每件物品有一個(gè)系數(shù),這件物品的費(fèi)用和價(jià)值均是原來的費(fèi)用和價(jià)值乘以這個(gè)系數(shù)。使這些系數(shù)分別為 1,2,4,...,2^(k-1),n[i]-2^k+1,且k是滿足n[i]-2^k+1>0的最大整數(shù)。例如,如果n[i]為13,就將這種 物品分成系數(shù)分別為1,2,4,6的四件物品。
分成的這幾件物品的系數(shù)和為n[i],表明不可能取多于n[i]件的第i種物品。另外這種方法也能保證對(duì)于0..n[i]間的每一個(gè)整數(shù),均可以用若干個(gè)系數(shù)的和表示,這個(gè)證明可以分0..2^k-1和2^k..n[i]兩段來分別討論得出,并不難,希望你自己思考嘗試一下。
這樣就將第i種物品分成了O(log n[i])種物品,將原問題轉(zhuǎn)化為了復(fù)雜度為<math>O(V*Σlog n[i])的01背包問題,是很大的改進(jìn)。
以上內(nèi)容來自背包九講之多重背包問題
#include<iostream> #include<algorithm> #define maxn 100010 using namespace std; int dp[maxn],n,k; int v[101],w[101],V; void zero(int cost) {for(int i=V;i>=cost;i--)dp[i]=max(dp[i],dp[i-cost]+cost); } void complet(int cost) {for(int i=cost;i<=V;i++)dp[i]=max(dp[i],dp[i-cost]+cost); } void multi(int cost,int amount) {if(cost * amount>=V){complet(cost);return ;}int k=1;while(k<amount){zero(k*cost);amount-=k;k<<=1;}zero(amount*cost); } int main() {while(scanf("%d %d",&n,&V)==2&&(n||V)){for(int i=0;i<n;i++)scanf("%d",&v[i]);for(int i=0;i<n;i++)scanf("%d",&w[i]);for(int i=1;i<=V;i++)dp[i]=INT_MIN;dp[0]=0;for(int i=0;i<n;i++)multi(v[i],w[i]);int count=0;for(int i=1;i<=V;i++)if(dp[i]>=0)count++;printf("%d\n",count);}return 0; }?
轉(zhuǎn)載于:https://www.cnblogs.com/nanke/archive/2011/11/30/2269080.html
總結(jié)
以上是生活随笔為你收集整理的hdu2844 Coins(普通的多重背包 + 二进制优化)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 访问网页
- 下一篇: SQL 16进制数转化10进制