[题解向] [Luogu1441] 砝码称重
\(\color{red}{\mathcal{Description}}\)
\(\color{red}{\mathcal{Solution}}\)
思路:\(01\)背包方案数 + \(bitset\) + 子集枚举
首先我的\(dfs\)菜的一匹,所以说一看这道题我就放弃了\(dfs\)
我们考虑子集枚举选取\(n-m\)个物品时的状态,然后对于每一个状态进行一次\(bool\)类型的\(01\)背包,最后统计\(max\)即可。
但是显然我们的复杂度会达到
\]
其中第一项是枚举子集的复杂度,之后是\(01\)背包方案数 + 扫一遍 + 清零+求出背包容量\(t\)的复杂度。
显然不足以\(1s\)过。那么我们不妨思考一个简单的优化,我们枚举状态从\(1 <<(n - m - 1)\)开始,因为当位数小于\(n - m\)时,永远选不够\(n-m\)个。并且我们可以预处理出每个状态的\(1\)的个数,那么我们就会有\(T(n) = 2^n-2^{n-m} +C_{n}^{m}\cdot (n \sum a_i + 3n) -> \Theta(max(2^n - 2^{n-m}, C_{n}^{m} \cdot n\sum a_i))\)
好像还可以的吧,但事实上我们还可以更优,我们直接考虑用\(bitset\)作为\(dp\)数组,然后就会有\(3 \cdot\frac{n}{32}\)的检测复杂度,好像可以优化些常数。
最后我还用了
inline int max(int a, int b) {return b - (b - a & (b - a >> 31));}
的毒瘤优化,但是依旧很慢——不过这不能阻止人类否定\(dfs\)的一家独大。
\(qwq\)
#include <bitset>
#include <cstdio>
#include <iostream>
#define MAX 5000
using namespace std ;
int i, j, k, d, t ; bitset <MAX> dp ;
int N, M, base[MAX], Len[MAX << 8], Max, Ans ;
inline int max(int a, int b) {return b - (b - a & (b - a >> 31));}
int main(){
cin >> N >> M ; d = N - M, Max = (1 << N) - 1 ;
for (i = 1 ; i <= N ; ++ i) cin >> base[i] ;
for (i = 1 ; i <= Max ; ++ i) Len[i] = Len[i - (i & -i)] + 1 ;
for (i = 1 << d - 1; i <= Max ; ++ i){
if(Len[i] == d){
dp.reset(), dp[0] = 1, t = 0 ;
for (j = 0 ; j < N ; ++ j) t += (1 << j & i) ? base[j + 1] : 0 ;
for (k = 0 ; k < N ; ++ k)
for (j = t ; j >= base[k + 1] ; -- j)
dp[j] = (1 << k & i) ? dp[j] : (dp[j] | dp[j - base[k + 1]]) ;
Ans = max(Ans, (int)dp.count() - 1) ;
}
}
cout << Ans << endl ; return 0 ;
}
[题解向] [Luogu1441] 砝码称重的更多相关文章
- luogu1441 砝码称重
搜索+背包就是了 #include <iostream> #include <cstring> #include <cstdio> using namespace ...
- 51nod 1837 砝码称重【数学,规律】
题目链接:51nod 1837 砝码称重 小 Q 有 n 个砝码,它们的质量分别为 1 克. 2 克.……. n 克. 他给 i 克的砝码标上了编号 i (i = 1, 2, ..., n),但是编号 ...
- Codevs 2144 砝码称重 2
2144 砝码称重 2 时间限制: 1 s 空间限制: 16000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 有n个砝码,现在要称一个质量为m ...
- BZOJ 1192 [HNOI2006]鬼谷子的钱袋:二进制 砝码称重问题
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1192 题意: 鬼谷子带了a元钱,他要把a元钱分装在小袋子中,使得任意不大于a的数目的钱,都 ...
- codevs 2144 砝码称重2
传送门 2144 砝码称重 2 时间限制: 1 s 空间限制: 16000 KB 题目等级 : 钻石 Diamond 题解 题目描述 Description 有n个砝码,现在要称一个质量为m ...
- P2347 砝码称重(动态规划递推,背包,洛谷)
题目链接:P2347 砝码称重 参考题解:点击进入 纪念我第一道没理解题意的题 ''但不包括一个砝码也不用的情况'',这句话我看成了每个砝码起码放一个 然后就做不出来了 思路: 1.这题数据很小,10 ...
- 51 Nod 1449 砝码称重
1449 砝码称重 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 收藏 关注 现在有好多种砝码,他们的重量是 w0,w1, ...
- NOI题库--砝码称重V2(多重背包2^n拆分)
以前只会写多重背包的原版,渣的不行,为了做此题不得不学习了一下,发现其实也不难,只要理解了方法就好多了(PS:其实和倍增挺像的) 8756:砝码称重V2 总时间限制: 1000ms 内存限制: 655 ...
- Codevs No.2144 砝码称重2
2016-05-31 22:01:16 题目链接: 砝码称重2 (Codevs No.2144) 题目大意: 给定N个砝码,求称出M的重量所需砝码最小个数 解法: 贪心 使砝码数量最小,当然是每个砝码 ...
随机推荐
- HTML+css基础 p段落标签 a 超链接标签 Src和href有什么区别和关联? target属性 Meta标签
p段落标签: <p></p> 1.他是唯一一个可以不写结束标签的双标签. a 超链接标签: 从一个页面链接到另一个页面.靠的是href属性. Src和href有什么区别和关联 ...
- dns攻击包代码实现
博客地址:http://home.cnblogs.com/u/zengjianrong/ 代码没有做好精简,有些多余的没有删去,因为博主太懒了哈哈 #include <stdio.h> # ...
- [转帖]CHROME开发者工具的小技巧
CHROME开发者工具的小技巧 https://coolshell.cn/articles/17634.html 需要仔细学习看一看呢. 2017年01月19日 陈皓 评论 58 条评论 64,08 ...
- c++中获得对象类型 typeid 与 type_info
复杂部分略去,摘录要素如下: 1.typeid是C++的关键字之一,等同于sizeof这类的操作符. 2.typeid操作符的返回结果是名为type_info的标准库类型的对象的引用(在头文件type ...
- WPF Adorner 弹出式工具栏 例子
源于MSDN 一个问题. 问:如何做出类似word的文字选中后工具栏弹出和动画效果. 我用的是adorner,其实用popup也是可以的. 效果图: 中间黑色部分代表真正的工具栏. xaml代码: & ...
- Docker安装及简单使用
1.docker安装 #1.检查内核版本,必须是3.10及以上 uname -r #2.安装 yum -y install docker 2.docker简单使用 #1.启动docker system ...
- vue-如何实现带参数跳转页面
[前后端分离项目之vue框架经验总结] 文/朱季谦 在vue框架的前端页面上,若要实现页面之间的带参数跳转,可参考以下实现过程: 例如,点击截图中的“查看试卷”,可实现带参跳转到相应的试卷页面,该功能 ...
- MVC+Ninject+三层架构+代码生成 -- 总结(四、數據層)
1.數據層使用了SqlSugar 庫類 . 數據層使用了SqlSugar 庫類 ,有興趣的 可以學習 http://www.codeisbug.com/Doc/8/1133,個人覺得比EF 簡單,容 ...
- webapi ClaimsPrincipal使用
参考文档:ClaimsPrincipal Class 个人demo:SwaggerDemoApi 今天看到一段代码懵逼了 var principal = new ClaimsPrincipal(new ...
- Android viewPager+fragment实现滑页效果
先上图,手指在手机向左或者向右滑就可以实现相应的页面切换. 先看activity_main.xml文件,非常简单,主要是三个标题TextView和viewpager <?xml version= ...