今天在寫到多重背包的題的時候,本來想着按老方法一個個循環添加,沒想到這次超時了,就找下了下優化的方法,果然找到了
二進制優化
不得不說是真的牛逼,智商差距啊 智商差距啊!
好了,下面正題
首先,之前的方法是這樣的
假如我們 東西的價值是 Val[] 數組,對應數量是 Num[]數組 ,一共有 n件東西
那按照老方法是 把數量大於一件的,全部抽出來添加在 Val[]數組,也就是說我們把這些大於一件的東西,全部當成 新的一件並且價值相同的 東西。代碼如下:
#include<iostream> using namespace 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 <= spe; i++) { //核心代碼 for (int j = 1; num[i] > j; j <<= 1)//注意j用到二進制位移 { sale[++count] = sale[i] * j; wei[count] = wei[i] * j; num[i] -= j; } wei[i] = wei[i] * num[i]; sale[i] = sale[i] * num[i]; }