简单瞎搞题(位运算优化背包问题)

本文介绍了一种使用位运算和bitset数据结构优化解决背包问题的方法。通过将dp数组的布尔值转换为二进制位,大大减少了空间需求和运算次数,使得在给定条件下求解问题变得高效可行。
摘要由CSDN通过智能技术生成

题目链接

这可不是瞎搞,出题人是有bear来。查资料时遇见的例题,当练习写一下。做法是位运算bitset优化的背包。


思路:

相当于有 n n n 组,每组选一个物品,然后问最后得到的重量之和是多少。不看位运算优化的话,和这个D题有点像。

朴素想法是设 d p [ i ] [ j ] dp[i][j] dp[i][j] 表示能否取得前 i i i 组,重量之和为 j j j 的状态, d p dp dp 值是个 b o o l bool bool 表示能否取到这个状态。但是这样重量可以是 1 0 6 10^6 106 的,组数是 100 100 100,运算次数 100 ∗ 100 ∗ 1 0 6 = 1 0 10 100*100*10^6=10^{10} 100100106=1010 ,时间空间都过不去。

我们不用 b o o l bool bool 值来存储状态,而是用一个二进制位来存储。这样就可以写成 b i t s e t < 1000001 > d p [ i ] bitset<1000001> dp[i] bitset<1000001>dp[i] d p [ i ] [ j ] dp[i][j] dp[i][j] 仍然可以表示和上面同样的意义,但是这时我们可以使用位运算,空间还只有原来的 1 64 \frac1{64} 641,运算次数变成 2 ∗ 1 0 8 2*10^8 2108 不到,反正卡过去了。

第一维还能滚动优化。

code:

#include <iostream>
#include <cstdio>
#include <bitset>
using namespace std;

int n;
bitset<1000001> dp[2];

int main(){
	cin>>n;
	dp[0]=1;
	for(int i=1,l,r;i<=n;i++){
		cin>>l>>r;
		auto &pre=dp[(i-1)&1],&t=dp[i&1];
		t.reset();
		for(int x=l;x<=r;x++){
			t|=pre<<x*x;
		}
	}
	cout<<dp[n&1].count();
	return 0;
}
  • 30
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值