\(\color{red}{\mathcal{Description}}\)

\(Link\)

\(\color{red}{\mathcal{Solution}}\)

思路:\(01\)背包方案数 + \(bitset\) + 子集枚举

首先我的\(dfs\)菜的一匹,所以说一看这道题我就放弃了\(dfs\)

我们考虑子集枚举选取\(n-m\)个物品时的状态,然后对于每一个状态进行一次\(bool\)类型的\(01\)背包,最后统计\(max\)即可。

但是显然我们的复杂度会达到

\[T(n) = 2^n \times (n \sum a_i + 3n) -> \Theta(2^nn\sum a_i)
\]

其中第一项是枚举子集的复杂度,之后是\(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] 砝码称重的更多相关文章

  1. luogu1441 砝码称重

    搜索+背包就是了 #include <iostream> #include <cstring> #include <cstdio> using namespace ...

  2. 51nod 1837 砝码称重【数学,规律】

    题目链接:51nod 1837 砝码称重 小 Q 有 n 个砝码,它们的质量分别为 1 克. 2 克.……. n 克. 他给 i 克的砝码标上了编号 i (i = 1, 2, ..., n),但是编号 ...

  3. Codevs 2144 砝码称重 2

    2144 砝码称重 2  时间限制: 1 s  空间限制: 16000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 有n个砝码,现在要称一个质量为m ...

  4. BZOJ 1192 [HNOI2006]鬼谷子的钱袋:二进制 砝码称重问题

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1192 题意: 鬼谷子带了a元钱,他要把a元钱分装在小袋子中,使得任意不大于a的数目的钱,都 ...

  5. codevs 2144 砝码称重2

    传送门 2144 砝码称重 2  时间限制: 1 s  空间限制: 16000 KB  题目等级 : 钻石 Diamond 题解   题目描述 Description 有n个砝码,现在要称一个质量为m ...

  6. P2347 砝码称重(动态规划递推,背包,洛谷)

    题目链接:P2347 砝码称重 参考题解:点击进入 纪念我第一道没理解题意的题 ''但不包括一个砝码也不用的情况'',这句话我看成了每个砝码起码放一个 然后就做不出来了 思路: 1.这题数据很小,10 ...

  7. 51 Nod 1449 砝码称重

    1449 砝码称重  题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 现在有好多种砝码,他们的重量是 w0,w1, ...

  8. NOI题库--砝码称重V2(多重背包2^n拆分)

    以前只会写多重背包的原版,渣的不行,为了做此题不得不学习了一下,发现其实也不难,只要理解了方法就好多了(PS:其实和倍增挺像的) 8756:砝码称重V2 总时间限制: 1000ms 内存限制: 655 ...

  9. Codevs No.2144 砝码称重2

    2016-05-31 22:01:16 题目链接: 砝码称重2 (Codevs No.2144) 题目大意: 给定N个砝码,求称出M的重量所需砝码最小个数 解法: 贪心 使砝码数量最小,当然是每个砝码 ...

随机推荐

  1. AngularJS入门Demo

    1 :表达式 <html> <head> <title>入门小Demo-1</title> <script src="angular.m ...

  2. JS修改URL参数,并修改前页面的地址

    function changeURLArg(url,arg,arg_val){ var pattern=arg+'=([^&]*)'; var replaceText=arg+'='+arg_ ...

  3. tomcat 下 base64图片上传超过2m的解决方案

    方案一: tomcat部署下默认post请求提交参数大小为2M左右,超过这个大小,就会传值不成功 要使post请求参数无大小限制,需要在server.xml上修改,如下: <Connector ...

  4. Web应急:搜索引擎劫持

    当你直接打开网址访问网站,是正常的,可是当你在搜索引擎结果页中打开网站时,会跳转到一些其他网站,比如博彩,虚假广告,淘宝搜索页面等.是的,你可能了遇到搜索引擎劫持. 现象描述 从搜索引擎来的流量自动跳 ...

  5. sql 按指定规则排序,例如 按 1,3,2排序 而不是1,2,3

    我们都知道 sql语句中的排序有desc(降序).asc(升序),这两个都是按顺序排列的,最近有一个需求是不按顺序排序了 ,抽出个别的排在前面,并且这种需求是应对的问题中的数据是比较少的,而且没有规律 ...

  6. 完美转发(perfect forwarding)、universal reference、引用折叠(collasping)

    首先要分清: C++里的值只有两种值:左值.右值.—— 其本质应该是内存中存储的值/instance分两种:一种是持久的,一种是“短暂的” 也只有两种引用: 左值引用.右值引用. ——引用,就是这个内 ...

  7. 49道spring面试题整理,附带答案

    1.选择使用Spring框架的原因? 使用Spring: 第一是使用它的IOC功能,在解耦上达到了配置级别. 第二是使用它对数据库访问事务相关的封装. 第三就是各种其他组件与Spring的融合,在Sp ...

  8. 安装Ubuntu linux

    (1)下载Ubuntu http://www.ubuntu.com/download/desktop (2)制作启动U盘 1. 启动Rufus: 2. 插入U盘: 3. Rufus会提示更新,以自动选 ...

  9. JavaScript正则表达式进阶指南

    摘要:正则表达式是程序员的必备技能,想不想多学几招呢? 本文用JavaScript的exec方法来测试正则表达式. 例如,正则表达式**/F.*g/会匹配"以F开头,以g结尾的字符串&quo ...

  10. C++ OpenSSL 之二:生成RSA文件

    1.等同于生成private key: openssl genrsa -out "save_path" 2048 2.代码如下 bool MakeRsaKeySSL(const c ...