多重揹包的二進位制優化
阿新 • • 發佈:2018-11-19
今天在寫到多重揹包的題的時候,本來想著按老方法一個個迴圈新增,沒想到這次超時了,就找下了下優化的方法,果然找到了
二進位制優化
不得不說是真的牛逼,智商差距啊 智商差距啊!
好了,下面正題
首先,之前的方法是這樣的
假如我們 東西的價值是 Val[] 陣列,對應數量是 Num[]陣列 ,一共有 n件東西
那按照老方法是 把數量大於一件的,全部抽出來新增在 Val[]陣列,也就是說我們把這些大於一件的東西,全部當成 新的一件並且價值相同的 東西。程式碼如下:
#include<iostream> usingnamespace std; int main() { int n; int wei[100], val[100], num[100];//物品的重量、價值、數量 cin >> n;//讀入一共有幾種物品 //讀入物品的資訊 for (int i = 1; i <= n; i++) { cin >> wei[i] >> val[i] >> num[i]; } //下面是核心 int tail = n; //從第一件產品開始列舉 for (int j = 1; j <= n; j++) { while (num[j]!=1)//如果該件產品的數量不是1件的話 { tail++;//尾部加一 //新增在尾部,補充好物品的資訊 wei[tail] = wei[j]; val[tail] = val[j]; num[tail] = 1; } } return 0; }
這種方法應該也就我這種腦子想的,其實還有點問題,就是如果物品數是0的話,還得再加一個判斷把該物品刪除了。
然後就是TLE了,所以下面是優化的方法!
——————————————————分割線——————————————————————————————
二進位制優化。
簡單來說,就是把一個數字分成 (1 2 4 8.........最大數) 這樣下去的型別
為什麼呢? 因為這些數字可以組成(1~最大數)中的任何一個數。
其實思路還是和上面的一樣,還是把這些抽出來變成一個新的產品,不過 重量和價值 有所不同。
例如變成:
一件 val[i]*1 wei[i]*1
一件 val[i]*2 wei[i]*2
一件 val[i]*4 wei[i]*4
一件 val[i]*8 wei[i]*8
以此類推,這樣比如我們要放 該產品4件 那就可以用我們 之前抽出來的變成的 新產品 代替。
for(int i=1;i<=種類數;i++) { int k=1; //對於每一種,k準備取1 2 4 8... int temp=m[i]; //m[i]為第i種的數量 for(k; k<=temp ; k*=2) { value[++num]=k*v[i]; //v[i]為第i種的每個的價值 temp-=k; } if(temp>0) value[++num]=temp*v[i]; }