C++标准库:bitset 用法整理&&zoj 3812
题意:给出N种药,每种药有两个属性,重量W,伤害值T。给出Q种疾病,每个疾病也有两个属性:重量M,伤害值S。现在要求你对每种疾病设计选择药的方案,使:1.每种要至多使用一次。2.选出的药的重量的和等于该疾病的重量,选出的药的伤害值的和等于该疾病的伤害值。如果存在方案,输出任何一个方案。否则,输出No solution.
思路:很容易想到这是恰好装满的01背包问题。但是因为T的范围为200000,同时还要输出方案,会感到无从下手。。
我们需要解决的问题有两个:因为T的范围非常大,如何保存dp的状态是个问题。同时也造成了无法直接保存最终的方案。
我们首先求出dp方程。和多重部分和问题不同,这里的选择只有01,所以我们用一个bool类型来表示方案是否存在即可。则设dp[i]j][k]表示考虑前i种药,重量之和为j,伤害值为k的方案是否存在,取值为0或1.状态转移方程为:dp[i+1][j+w[i]][k+t[i]] |= dp[i][j][k]( |= 表示位运算或)。但是,如果直接用int保存该状态,会造成空间的极大浪费。所以我们用bitset类保存该状态,即在第三维用bitset保存。 则状态转移方程为:dp[i+1][j+w[i]][k<<t[i]]
|= dp[i][j][k]。
但是,三维的dp也会爆内存,所以我们用滚动数组的方式来求最终的状态。
而对于第二个问题,我们可以用搜索的方法解决。但是因为爆搜的复杂度是2^400,根本无法进行。在这道题中,我们虽然不能把三维的数组全部开满,但是我们可以将药进行分组,每一组记录一次dp状态,最后再搜索的时候,利用记录还原方案。(自己感觉有点可持久化数据结构的味道)。
代码如下:
using namespace std;
const int MAX = 43;
const int MAXN = 410;
const int MAXA = 51;
const int MAXB = 200001;
int N,Q,T;
int tot,m,s;
int w[MAXN],t[MAXN];
bool sig;
bitset<MAXB> archive[MAX][MAXA],dp[MAXA];
int ans[MAXN],sz;
bool dfs(int n, int m, int s)
{
if(sig) return sig;
if(m == 0 && s == 0){
return sig = true;
}
int now = n / 10;
if(n % 10) now++;
if(archive[now][m][s] == 0)
return false;
if(m >= w[n] && s >= t[n]){
ans[sz++] = n;
if(!dfs(n-1,m - w[n],s - t[n]))
sz--;
}
return dfs(n-1,m,s);
}
int main(void)
{
//freopen("input.txt","r",stdin);
//freopen("out.txt","w",stdout);
scanf("%d", &T);
while(T--){
scanf("%d %d", &N, &Q);
for(int i = 1 ; i <= N; ++i)
scanf("%d %d", &w[i],&t[i]);
for(int i = 0 ; i <= 50; ++i)
dp[i].reset();
tot = 0;
dp[0][0] = 1;
for(int i = 1; i <= N; ++i){
for(int j = 50; j >= w[i]; --j)
dp[j] |= (dp[j - w[i]]<<t[i]);
if(i == N || i % 10 == 0){
tot++;
for(int j = 0; j <= 50; ++j)
archive[tot][j] = dp[j];
}
}
while(Q--){
scanf("%d %d", &m,&s);
if(dp[m][s]){
sz = 0;
sig = false;
dfs(N,m,s);
for(int i = 0; i < sz; ++i)
printf("%d%c",ans[i],i == sz -1?'\n':' ');
}
else
puts("No solution!");
}
}
return 0;
}
</span>
C++标准库:bitset 用法整理&&zoj 3812的更多相关文章
- 把《c++ primer》读薄(3-3 标准库bitset类型)
督促读书,总结精华,提炼笔记,抛砖引玉,有不合适的地方,欢迎留言指正. //开头 #include <bitset> using std::bitset; 问题1.标准库bitset类型( ...
- C++标准库 bitset
本文地址:http://www.cnblogs.com/archimedes/p/cpp-bitset.html,转载请注明源地址. 有些程序要处理二进制位的有序集,每个位可能包含 0(关)1(开)值 ...
- C++标准库bitset类型(简单使用方法)
转自此人博客 ```cpp #include<bister> using std::bitset; ``` 一句话定义:可自定义位数,用作记录二进制的数据类型. 一,定义和初始化 ```c ...
- C++ 标准库类型-String,Vector and Bitset
<C++ Primer 4th>读书摘要 最重要的标准库类型是 string 和 vector,它们分别定义了大小可变的字符串和集合.这些标准库类型是语言组成部分中更基本的那些数据类型(如 ...
- 【BZOJ 1923】1923: [Sdoi2010]外星千足虫 (高斯消元异或 | BITSET用法)
1923: [Sdoi2010]外星千足虫 Description Input 第一行是两个正整数 N, M. 接下来 M行,按顺序给出 Charles 这M次使用“点足机”的统计结果.每行 包含一个 ...
- C++primer第三章标准库类型
除第二章介绍的基本数据类型外,C++ 还定义了一个内容丰富的抽象数据类型标准库. 本章将介绍标准库中的 vector.string 和 bitset 类型. string 类型支持长度可变的字符串 v ...
- 1.Python3标准库--前戏
Python有一个很大的优势便是在于其拥有丰富的第三方库,可以解决很多很多问题.其实Python的标准库也是非常丰富的,今后我将介绍一下Python的标准库. 这个教程使用的书籍就叫做<Pyth ...
- Primer回顾 标准库类型
string类型的输入操作符: 1.读取并忽略开头所有的空白字符(如空格,换行符,制表符). 2.读取字符直至再次遇到空白字符,读取终止. 用getline读取整行文本 getline.接受两个参 ...
- 《JavaScript语言入门教程》记录整理:运算符、语法和标准库
目录 运算符 算数运算符 比较运算符 布尔运算符 二进制位运算符 void和逗号运算符 运算顺序 语法 数据类型的转换 错误处理机制 编程风格 console对象和控制台 标准库 Object对象 属 ...
随机推荐
- 洛谷2019 3月月赛 T2
题干 洛谷同款 T2?(看似比T1简单些) 二维前缀和嘛?[多简单 我天天拿二维前缀和水DP] 这是前缀和的预处理 2333 处理出来所有的情况 某个地方要加上mod再%mod 如果没有这一步 那么 ...
- 2017杭电多校06Rikka with Graph
Rikka with Graph Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
- 2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛-B-Perfect Numbers(完数)
题目描述 We consider a positive integer perfect, if and only if it is equal to the sum of its positive d ...
- magento getUrl函数跳转admin模块问题
在用以下代码时,跳转后的url里面会是空的,即没有admin这个值 $this->getUrl('admin/catalog_product/edit', array('id' => $c ...
- 01按照官方步骤编译NanoPiM1Plus的Android
01按照官方步骤编译NanoPiM1Plus的Android 大文实验室/大文哥 壹捌陆捌零陆捌捌陆捌贰 21504965 AT qq.com 完成时间:2017/12/6 10:58 版本:V1.0 ...
- JPQL 模糊查询,查询条件拼接(like使用)
@Transactional public List<ViewCorplist2> findAllCorpsLikeK(String kw) { System.out.println(kw ...
- Java 基础入门随笔(10) JavaSE版——单例设计模式
设计模式:对问题行之有效的解决方式.其实它是一种思想. 1.单例设计模式. 解决的问题:就是可以保证一个类在内存中的对象唯一性.(单个实例) 使用单例设计模式需求:必须对于多个程序使用同一个配置信息对 ...
- 史上最大型广告欺诈活动Methbot:黑客是如何每天赚到500万美元的
根据国外安全专家的最新报告,有一群黑客正在对美国的知名企业和媒体机构进行广告欺诈活动,而这群黑客每天都可以从中赚取三百万到五百万美金. 是的,你没看错,这绝对是人类历史上最牛X的恶意广告欺诈活动!不过 ...
- Masonry 原理与使用说明
原理: 1)约束生成:MASConstraintMaker: 2)缺省补齐: - (void)setSecondViewAttribute:(id)secondViewAttribute { if ( ...
- 个人作业Alpha项目测试
这个作业属于哪个课程 软件工程原理 这个作业要求在哪里 作业要求 团队名称 TEAMPANTHER 这个作业的目标 每个同学必须选取非自己所在团队的3个项目进行测试. 在你所测试的项目的Alpha发布 ...