StkOvflow

STACK OVERFLOW!

一言(ヒトコト)

loj.ac
——lmh

AcWing.7 混合背包问题

题目描述

N 种物品和一个容量是 V 的背包。

物品一共有三类:

  • 第一类物品只能用1次(01背包);
  • 第二类物品可以用无限次(完全背包);
  • 第三类物品最多只能用 si 次(多重背包);

每种体积是 vi,价值是 wi

求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。

解题思路

由于多重背包经过二进制拆分之后会变成以2k为数量的log2si堆,我们可以在这些堆上做01背包,所以我们就把这个混合背包搞成了两类:

a.si=0,此时在题目的描述中是完全背包,做一遍完全就行。

b.si0此时我们就是01或者多重了,那01我们可以看成是每个物品最多用1次,也就是所有的si都是1,然后做二进制优化的多重背包即可

代码

#include <iostream>

using namespace std;

const int N = 1010;
int f[N], n, m;

int main() 
{
    scanf("%d%d", &n, &m);
        
    for (int i = 1; i <= n; i ++ ) 
    {
        int v, w, s;
        scanf("%d%d%d", &v, &w, &s);
        
        if (s == 0) //当完全背包做
        {
            for (int j = v; j <= m; j ++ ) 
                f[j] = max(f[j], f[j - v] + w);
        }
        else //转化为01背包
        {
            if (s == -1) s = 1;
            
            for (int k = 1; k <= s; k <<= 1) 
            {
                for (int j = m; j >= v * k; j -- ) 
                    f[j] = max(f[j], f[j - v * k] + w * k);
                s -= k;
            }
            
            if (s) for (int j = m; j >= s * v; j -- )
                f[j] = max(f[j], f[j - v * s] + w * s);
        }
    }
    
    printf("%d\n", f[m]);
    
    return 0;
}

AC!

posted @   StkOvflow  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示