第三讲 多重背包问题②——二进制优化

【题目来源】AcWing 5. 多重背包问题 II

【题意分析】根据当前数据范围, O ( n 3 ) O(n^3) O(n3) 的时间复杂度过不了,最多为 O ( n 2 l o g n ) O(n^2logn) O(n2logn)
【优化方法】
二进制优化 0 / 1 0/1 0/1 背包部分:
对于当前 0 / 1 0/1 0/1 背包部分,我们用 k k k 个物品来表示装入 1 1 1 ~ k k k 个物品的情况,比如;
有一个物品有 15 15 15 个,且符合 0 / 1 0/1 0/1 背包,那么我们需要循环 15 15 15 次,即:

但是可以计算 15 15 15 以内有哪些 2 2 2 的幂次方数:

此时出现了 3 3 3 2 2 2 的幂次方数, 2 2 2 4 4 4 8 8 8,剩余 1 1 1,那么 1 1 1 2 2 2 4 4 4 8 8 8 这四个数可以组成 0 0 0 ~ 15 15 15 的任意一种情况:

因此,可以通过下图来理解该方法对时间复杂度的优化方法:

从对 15 15 15 个物品做 0 / 1 0/1 0/1 背包优化为了给 4 4 4 个物品做 0 / 1 0/1 0/1 背包, O ( n ) O(n) O(n)优化为了 O ( l o g 2 n ) O(log_2n) O(log2n)
整个算法 O ( n 3 ) O(n^3) O(n3) 优化为了 O ( n 2 l o g n ) = 1000 ∗ l o g 2 2000 ∗ 2000 ≈ 1000 ∗ 11 ∗ 2000 = 2.2 ∗ 1 0 7 O(n^2logn) = 1000 * log_22000*2000 ≈ 1000 * 11 * 2000 = 2.2 * 10^7 O(n2logn)=1000log2200020001000112000=2.2107 1000 m s 1000ms 1000ms 能过,代码如下:

#include<iostream>
using namespace std;
struct node{
  int v, w;
} q[2000050];
int n, m, V, dp[2050], a, b, c;

int main(){
  cin >> n >> V;
  for(int i = 1; i <= n; i ++){
    cin >> a >> b >> c;
    //关键代码:begin
    int k = 1;
    while(k <= c){
      m ++;
      q[m].v = k * a;
      q[m].w = k * b;
      c -= k;
      k *= 2;
    }
    if(c > 0){
      m ++;
      q[m].v = c * a;
      q[m].w = c * b;
    }
    //关键代码:end
  }
  for(int i = 1; i <= m; i ++)
    for(int j = V; j >= q[i].v; j --)
      dp[j] = max(dp[j], dp[j - q[i].v] + q[i].w);
  cout << dp[V];
  return 0;
}
  • 18
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值