多重背包问题 一句话说清楚“二进制拆分“

目录

区别:

一句话说清楚:

板子:


区别:

得先懂完全背包问题完全背包问题 非零基础-CSDN博客

都是让背包内价值最大。

完全背包问题每种物品可以取无数次。而多重背包问题每件取的次数有限。

都可以用的最挫的方法就是0~k件去遍历。

完全背包问题可以推出公式优化(或者说逻辑上可以直接一次从前往后遍历)

多重背包问题不好推公式。本文讲的是二进制拆分方法来优化(完全背包问题也可以用这个,但是不是最优)

可以参考大佬文章学习 背包九讲——全篇详细理解与代码实现-CSDN博客

练习题: P1776 宝物筛选 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

一句话说清楚:

一句话说清这个二进制拆分:

int 整形知道吧?只需要32位就可以表示 -2147483647 - 1 ~ 2147483647

有点感觉吗?

再细说:1可以表示1 , 2可以表示2 , 1和2一起可以表示3 ,但我们只需要用到两个数,不需要遍历1到3

板子:

目的:把num拆成二进制  (最后一位(即剩余)未必是2的倍数)

第 i 件物品 ,本次装 k 件 ,j 是当前背包大小

W 是背包大小

m[ i ]是该物品的数目,w[ i ]是该物品的大小 , v[ i ]是该物品的价值

num是最大数目 : 看能装多少 W / w[i] ,再看有多少m[ i ] 。数目够,就尽可能装。数目w[i]不够,那就全装进去。

	vector<ll>dp(MAX);
	for (int i = 1; i <= n; i++)
	{
		int num = min(m[i], W / w[i]);
		for (int k = 1; num > 0; k<<=1)
		{
			if (k > num)k = num;
			num -= k;
			for (int j = W; j >= 0; j--)
			{
				if (j - w[i] * k >= 0)
					dp[j] = max(dp[j], dp[j - w[i] * k] + v[i] * k);
			}
		}			
	}

if可以自行优化掉

ε≡٩(๑>₃<)۶ 一心向学,加油!

  • 14
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值