1. 程式人生 > >多重揹包的二進位制優化

多重揹包的二進位制優化

今天在寫到多重揹包的題的時候,本來想著按老方法一個個迴圈新增,沒想到這次超時了,就找下了下優化的方法,果然找到了

二進位制優化

不得不說是真的牛逼,智商差距啊 智商差距啊!

好了,下面正題

 

首先,之前的方法是這樣的

假如我們 東西的價值是  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<=種類數;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];  
    }