二進制思想和多重背包問題


二進制思想

問題描述:

  假設有1000個蘋果,現在要取n個蘋果,如何取?正常的做法應該是將蘋果一個一個拿出來,直到n個蘋果被取出來。

  又假設有1000個蘋果和10只箱子,如何快速的取出n個蘋果呢?可以在每個箱子中放 2^i (i<=0<=n)個蘋果,也就是 1、2、4、8、16、32、64、128、256、489(最后的余數),相當於把十進制的數用二進制來表示,取任意n個蘋果時,只要推出幾只箱子就可以了。

多重背包問題

問題描述:

  有N種物品和一個容量為V的背包。第 i 種物品最多有n[i]件可用,每件費用是c[i],價值是w[i]。求解將哪些物品裝入背包可使這些物品的費用總和不超過背包容量,且價值總和最大。

問題分析:

 

  很容易想到可以把該問題轉化成01背包問題來考慮,把每n[i] 中的每個物品都當成一個獨立的物品,而這 n[i] 個物品能夠表示的重量其實用 log n[i]個組合后的物品就能表示。

內層循環代碼如下:

int k, t;
k = 1;
t = n[i];
while(t > k)
{
    for(j=W; j>=c[i]*k; --j)
    {
        f[j] = max(f[j], f[j-c[i]*k] + w[i]*k);
    }
    t -= k;
    k *= 2;
}
for(j=W; j>=c[i]*t; --j)
{
    f[j] = max(f[j], f[j-c[i]*t] + w[i]*t);
}

poj上的1014是一道簡單的多重背包問題。http://poj.org/problem?id=1014

源碼如下:

View Code
 1 #include <stdio.h>
 2 #define max(x, y) ((x)>(y) ? (x) : (y)) 
 3 int f[80001];
 4 int main()
 5 {
 6     int c[7];
 7     int i, j;
 8     int m = 0;
 9     int nHarf = 0;
10     while(scanf("%d %d %d %d %d %d", &c[1], &c[2], &c[3], &c[4], &c[5], &c[6]) )
11     {
12         if(c[1]==0 && c[2]==0 && c[3]==0 && c[4]==0 && c[5]==0 && c[6]==0)
13         {
14             break;
15         }
16         printf("Collection #%d:\n", ++m);
17         nHarf = c[1]*1 + c[2]*2 + c[3]*3 + c[4]*4 + c[5]*5 + c[6]*6;
18         if(nHarf%2 == 1)
19         {
20             printf("Can't be divided.\n\n");
21             continue;
22         }
23         else
24         {
25             nHarf /= 2;
26         }
27         for(i=1; i<7; ++i)
28         {
29             if(c[i] == 0) continue;
30             if(c[i]*i > nHarf)
31             {
32                 for(j=i; j<=nHarf; ++j)
33                 {
34                     f[j] = max(f[j], f[j-i] + i);
35                 }
36             }
37             else
38             {
39                 int k, t;
40                 k = 1;
41                 t = c[i];
42                 while(t > k)
43                 {
44                     for(j=nHarf; j>=i*k; --j)
45                     {
46                         f[j] = max(f[j], f[j-i*k] + i*k);
47                     }
48                     t -= k;
49                     k *= 2;
50                 }
51                 for(j=nHarf; j>=i*t; --j)
52                 {
53                     f[j] = max(f[j], f[j-i*t] + i*t);
54                 }
55             }
56         }
57         if(f[nHarf] == nHarf)
58         {
59             printf("Can be divided.\n\n");
60         }
61         else
62         {
63             printf("Can't be divided.\n\n");
64         }
65         for(i=0; i<=nHarf; ++i)
66         {
67             f[i] = 0;
68         }
69     }
70     return 0;
71 }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM