多重揹包問題 II

2022-07-11 19:54:08 字數 2303 閱讀 7607

原題鏈結acwing5

基本思考框架

思路和多重揹包問題i一樣,但這題的資料範圍變成1000了,非優化寫法時間複雜度o(n^3) 接近 1e9必超時。

優化多重揹包的優化

首先,我們不能用完全揹包的優化思路來優化這個問題,因為每組的物品的個數都不一樣,是不能像之前一樣推導不優化遞推關係的。(詳情看下面引用的博文)

我們列舉一下更新次序的內部關係:

c++ f[i , j ] = max( f[i-1,j] , f[i-1,j-v]+w , f[i-1,j-2*v]+2*w , f[i-1,j-3*v]+3*w , .....) 

f[i , j-v]= max( f[i-1,j-v] , f[i-1,j-2*v] + w , f[i-1,j-2*v]+2*w , .....)

由上兩式,可得出如下遞推關係:

f[i][j]=max(f[i,j-v]+w , f[i-1][j])

接下來,我介紹乙個二進位制優化的方法假設有一組商品,一共有11個。我們知道,十進位制數字 11可以這樣表示

11=1011(b)=0111(b)+(11−0111(b))=0111(b)+0100(b)

正常揹包的思路下,我們要求出含這組商品的最優解,我們要列舉12次(列舉裝0,1,2....12個)。

現在,如果我們把這11個商品分別打包成含商品個數為1個,2個,4個,4個(分別對應0001,0010,0100,0100)的四個」新的商品 「, 將問題轉化為01揹包問題,對於每個商品,我們都只列舉一次,那麼我們只需要列舉四次 ,就可以找出這含組商品的最優解。 這樣就大大減少了列舉次數。

這種優化對於大數尤其明顯,例如有1024個商品,在正常情況下要列舉1025次 , 二進位制思想下轉化成01揹包只需要列舉10次。

優化的合理性的證明

先講結論:上面的1,2,4,4是可以通過組合來表示出0~11中任何乙個數的,還是拿11證明一下(舉例一下):

首先,11可以這樣分成兩個二進位制數的組合:

11=0111(b)+(11−0111(b))=0111(b)+0100(b)

其中0111通過列舉這三個1的取或不取(也就是對0001(b),0010(b),0100(b)的組合),可以表示十進位制數0~7( 剛好對應了 1,2,4 可以組合出 0~7 ) , 0~7的列舉再組合上0100(b)( 即 十進位制的 4 ) ,可以表示十進位制數 0~11。其它情況也可以這樣證明。這也是為什麼,這個完全揹包問題可以等效轉化為01揹包問題,有木有覺得很奇妙

怎麼合理劃分乙個十進位制數?

上面我把11劃分為

11=0111(b)+(11−0111(b))=0111(b)+0100(b)

是因為 0111(b)剛好是小於11的最大的尾部全為1的二進位制 ( 按照上面的證明,這樣的劃分沒毛病 ) , 然後那個尾部全為1的數又可以 分解為 0000....1 , 0000....10 , 0000....100 等等。

對應c++**:

//設有s個商品,也就是將s劃分

for(int k = 1 ; k <= s ;k*=2));}

if(s>0)

goods.push_back();

終究ac**:01優化+二進位制優化

#include#include#includeusing namespace std;

const int n = 2010;

int f[n],n,m;

struct good

;int main()

); }

if(s>0) good.push_back();

}//01揹包優化+二進位制

for(auto t : good)

for(int j = m ; j >= t.v ; j--)

f[j] = max(f[j] , f[j-t.v]+t.w ); //這裡就是f[j]

cout<

return 0;

}

多重揹包問題 II

有 n 種物品和乙個容量是 v 的揹包。第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品種數和揹包容積。接下來有 n 行,每行三個整數 vi...

多重揹包問題II

多重揹包問題ii 總體積是m,每個小物品的體積是a i 每個小物品的數量是b i 每個小物品的價值是c i 求能夠放入揹包內的最大物品能夠獲得的最大價值 和上乙個很類似 上一題體積就是價值,這裡的價值是單獨定義了 狀態轉移方程 不放a i f i j f i 1 j 放a j 可放多個設為k,k m...

多重揹包問題 II

有 n 種物品和乙個容量是 v 的揹包。第 i 種物品最多有 si 件,每件體積是 vi,價值是 wi。求解將哪些物品裝入揹包,可使物品體積總和不超過揹包容量,且價值總和最大。輸出最大價值。輸入格式 第一行兩個整數,n,v,用空格隔開,分別表示物品種數和揹包容積。接下來有 n 行,每行三個整數 vi...