背包问题

此文系阅读《背包问题九讲》之后的笔记 ,在此先此文作者表示敬意

简单01背包问题

考虑第i件物品放还是不放, 递推公式为:

f[i][v] = max{f[i-1][v], f[i-1][v-cost[i]] + weight[i]}

 

递推第i件物品时,必须知道i-1时的结果,所以用一维数组实现时,for循环倒退

#define N
#define V
int cost[N], weight[N];

for (i = 1; i <= N; ++i) {
   
for (v = V; v >= cost[i]; --v) 

      f[v] = max{f[v], f[v-cost[i]] + wight[i]};

 根据有么有要求背包刚好填满:

yes:初始化时除f[0] = 0;其他都初始化为无穷小

no: 都初始化为0


完全背包问题

每个物品可以放多次。

for (i = 1; i <= N; ++i) {
   
for (v = 0; v <= V; ++v) 

      f[v] = max{f[v], f[v-cost[i]] + wight[i]};


多重背包问题

每个物品有上界n[i], 和完全背包类似。

n[i]可以分为1、2、4、…… 2*k-1、n[i]-2^(k-1)系数乘以cost[i]。

原问题转化为了复杂度为O(V*Σlog n[i])的01背包问题 ,分成0..2^k-1和2^k..n[i]两段

for (i = 1; i < N; ++i) {
   
if (cost[i] * amount[i] >= V) {
      CompletePack(cost[i], weight[i]);
      
return;
   }
   
int k = 1;
   
while (k < amount[i]) {
      ZeroOnePack(k
*cost[i], k*weight[i]);
      amount[i] 
= amount[i] - k;
      k 
= k*2;
   }
   ZeroOnePack(amount[i]
*cost[i], amount[i]*weight[i]);

}

 混合三种背包问题

前面三种背包的集合,

for i=1..N
    
if 第i件物品属于01背包
        ZeroOnePack(c[i],w[i])
    
else if 第i件物品属于完全背包
        CompletePack(c[i],w[i])
    
else if 第i件物品属于多重背包
        MultiplePack(c[i],w[i],n[i])

 

 

 

 

posted @ 2009-03-08 20:41  断桥残雪  阅读(262)  评论(0)    收藏  举报