动态规划之背包问题

动态规划之背包问题

1.01背包问题
  • 题目描述:

有N件物品和一个容量为V的背包。放入第i 件物品耗费的空间是Ci ,得到的价值是Wi,求解将哪些物品装入背包可使价值总和最大。

  • 状态转移方程:

F[i][v] = max(F[i1][v],F[i1][vCi]+Wi)

i1,重量为v的状态下,放或者不放第i件物品。

  • 将二维转化至一维可得伪代码:复杂度:O(VN)
void ZeroOnePack(F,C,W)
{
    for v = V to C //从V到C是进行了优化
       F[v]=max{F[v],F[v-C]+W};
}
for i = 1 to N 
    ZeroOnePack(F,C[i],W[i]);
  • 初始化的细节问题:

如果要求恰好装满背包,则初始化时,F[0]=0 ,其余F[1V]=

若未要求恰好装满,则F[0V]=0

  • 个人对于代码的理解:

i 从1到n刷新数组,所以每一个i在使用数组时,都有i1使用过的痕迹,所以起到了状态的限制。

另外,v从V到0,当计算较大的v时,较小的v还没有放入i,所以保证了所有的物品只被放入一次。

2.完全背包问题
  • 题目描述:

有N种物品和一个容量为V的背包,每种物品都有无限件可以用,放入第i件物品耗费的空间是Ci,得到的价值是Wi。求解:将哪些物品放入背包,可使这些物品耗费的空间总和不超过背包的容量,且价值总和最大。

  • 状态转移方程:

F[i][v] = max(F[i1][v],F[i1][vkCi]+kWi)

F[i][v] = max(F[i1][v],F[i][vCi]+Wi)

  • 可能的优化方法:

去掉重量大于V的,对于cost相同的物品,只选择weight最大的

  • 伪代码:O(VN)
void CompletePack(F,C,W)
{
    for v = C to V 
       F[v]=max{F[v],F[v-C]+W};
}
for i = 1 to N 
    CompletePack(F,C[i],W[i]);
  • 个人对于代码的理解:

使v从C到V,当v较大时,较小的v已经被更新过,所以相当于可以重复往背包里放入同一个物体。

3.多重背包问题
  • 题目描述:

有N件物品和一个容量为V的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci,价值是Wi。求解将哪些物品装入背包可使这些物品耗费的空间总和不超过背包容量,且价值总和最大。

  • 状态转移方程:

F[i][v] = max(F[i1][v],F[i1][vkCi]+kWi)0kMi

  • 伪代码:O(VlogMi)
void MultiplePack(F,C,W,M)
{
  if(C*M>=V){
    CompletePack(F,C,W);
    return ;
  }
  k=1;
  while(k<M){
    ZeroOnePack(F,k*C,k*W);
    M=M-k;
    k=k*2;
    ZeroOnePack(F,M*C,M*W);
  }
}
  • 代码理解:

将多重背包转化为完全背包和01背包。如果物品对于背包不能视作完全,就将物品拆成1,2,4,8……的01背包。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页