砝码称重——突发奇想做的某一道题

\(\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 ;
}

\(by \ \ Flower\_ pks\)

原文地址:https://www.cnblogs.com/pks-t/p/9780351.html

时间: 2024-10-11 13:12:26

砝码称重——突发奇想做的某一道题的相关文章

【dp】砝码称重

砝码称重 来源:NOIP1996(提高组)  第四题 [问题描述]     设有1g.2g.3g.5g.10g.20g的砝码各若干枚(其总重<=1000),用他们能称出的重量的种类数. [输入文件]   a1  a2  a3  a4  a5  a6     (表示1g砝码有a1个,2g砝码有a2个,…,20g砝码有a6个,中间有空格). [输出文件]   Total=N     (N表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况). [输入样例]     1 1 0 0 0

砝码称重问题二

题目描述 有一组砝码,重量互不相等,分别为m1.m2.m3……mn:它们可取的最大数量分别为x1.x2.x3……xn. 现要用这些砝码去称物体的重量,问能称出多少种不同的重量. 现在给你两个正整数列表w和n, 列表w中的第i个元素w[i]表示第i个砝码的重量,列表n的第i个元素n[i]表示砝码i的最大数量.  i从0开始                   请你输出不同重量的种数.如:w=[1,2], n=[2,1], 则输出5(分析:共有五种重量:0,1,2,3,4) 解题 参考智力题砝码称重

洛谷P2347 砝码称重 [2017年4月计划 动态规划01]

P2347 砝码称重 题目描述 设有1g.2g.3g.5g.10g.20g的砝码各若干枚(其总重<=1000), 输入输出格式 输入格式: 输入方式:a1 a2 a3 a4 a5 a6 (表示1g砝码有a1个,2g砝码有a2个,…,20g砝码有a6个) 输出格式: 输出方式:Total=N (N表示用这些砝码能称出的不同重量的个数,但不包括一个砝码也不用的情况) 输入输出样例 输入样例#1: 1 1 0 0 0 0 输出样例#1: Total=3 暴力算法略,这里只讲dp.背包问题,每个砝码选或

砝码称重3

参考 https://blog.csdn.net/livelylittlefish/article/details/6555347 假设有280g盐,有一架天平,有两个砝码,分别是4g和14g .能否在3次内将280g食盐分为100g和180g两堆,请详细描述你的解决方法. 这是另外一种砝码称重问题,类似,但是又不同.砝码称重这个是给定无限数量砝码,只需计算能不能组成一个重量,不用知道如何组合.砝码称重1是给定砝码个数和重量,以及可以组合的重量,求出任意一种重量是如何组合的.砝码称重2给定重量和

1449 砝码称重

1449 砝码称重 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 现在有好多种砝码,他们的重量是 w0,w1,w2,...  每种各一个.问用这些砝码能不能表示一个重量为m的东西. 样例解释:可以将重物和3放到一个托盘中,9和1放到另外一个托盘中. Input 单组测试数据. 第一行有两个整数w,m (2 ≤ w ≤ 10^9, 1 ≤ m ≤ 10^9). Output 如果能,输出YES,否则输出NO. Input示例

2144 砝码称重 2

2144 砝码称重 2 http://codevs.cn/problem/2144/ 题目描述 Description 有n个砝码,现在要称一个质量为m的物体,请问最少需要挑出几个砝码来称? 注意一个砝码最多只能挑一次 输入描述 Input Description 第一行两个整数n和m,接下来n行每行一个整数表示每个砝码的重量. 输出描述 Output Description 输出选择的砝码的总数k,你的程序必须使得k尽量的小. 样例输入 Sample Input 3 10591 样例输出 Sa

HFUT 1354.砝码称重(安徽省2016“京胜杯”程序设计大赛 A)

砝码称重 Time Limit: 1000 MS Memory Limit: 65536 KB Total Submissions: 12 Accepted: 10 Description 小明非常喜爱物理,有一天,他对物理实验室中常用的弹簧拉力计产生了兴趣.实验室中有两种质量不同的砝码,小明分别用a个第一种砝码放在弹簧拉力计上和b个第二种砝码放在弹簧拉力计上,假设每增加单位重量的砝码,弹簧拉力计的长度增加1,那么两次称量弹簧拉力计的长度差是多少呢?(假设拉力计不发生非弹性形变) Input 第

蓝桥杯——说好的进阶之砝码称重(贪心算法)

5个砝码 用天平称重时,我们希望用尽可能少的砝码组合称出尽可能多的重量. 如果只有5个砝码,重量分别是1,3,9,27,81.则它们可以组合称出1到121之间任意整数重量(砝码允许放在左右两个盘中). 本题目要求编程实现:对用户给定的重量,给出砝码组合方案. 例如: 用户输入: 5 程序输出: 9-3-1 用户输入: 19 程序输出: 27-9+1 要求程序输出的组合总是大数在前小数在后. 可以假设用户的输入的数字符合范围1~121. public static void main(String

51nod 1449 砝码称重 (进制思想)

1449 砝码称重 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 现在有好多种砝码,他们的重量是 w0,w1,w2,...  每种各一个.问用这些砝码能不能表示一个重量为m的东西. 样例解释:可以将重物和3放到一个托盘中,9和1放到另外一个托盘中. Input 单组测试数据. 第一行有两个整数w,m (2 ≤ w ≤ 10^9, 1 ≤ m ≤ 10^9). Output 如果能,输出YES,否则输出NO.