【2015の复活】砝码称重v2

3 篇文章 0 订阅
1 篇文章 0 订阅

Problem

Background

设有 1g, 2g, 3g, 5g, 10g, 20g 的砝码各若干枚(其总重 ≤ 100, 000),要求:计算用这些砝码能称出的
不同重量的个数,但不包括一个砝码也不用的情况。

Input

一行,包括六个正整数 a 1 , a 2 , a 3 , a 4 , a 5 , a 6 ,表示 1g 砝码有 a 1 个,2g 砝码有 a 2 个,……,20g 砝码
有 a 6 个。相邻两个整数之间用单个空格隔开。

Output

以“Total=N”的形式输出,其中 N 为可以称出的不同重量的个数。

Example

weight.in
1 1 0 0 0 0
weight.out
Total=3

Explanation

样例给出的砝码可以称出 1g, 2g, 3g 三种不同的重量。

Scoring

• 对于 20% 的数据,砝码总个数不超过 20。
• 对于 40% 的数据,砝码总个数不超过 800。

Solution

也是一道NOI OpenJudge上的一道题
这题首先是一个背包问题,转移状态可行性。
dp[i][j]表示第i个包,总重为j的可行性
dp[i][j] |= dp[i - 1][j - k * c[i]]
然后采用二进制优化
用一个bitset,第i为表示重量为i的可行性
将每个 ai 拆分 20,21,222ki,pi
每次更新bitset即为 A|=A<<ciai
统计A中1的个数

Code

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = (a); i <= (b); i++)
#define red(i, a, b) for (int i = (a); i <= (b); i--)
#define ll long long

const int N = 110000;
int v[6] = {1, 2, 3, 5, 10, 20};
int sum, ans, m;
int k[10], f[150000], num[150000];
bitset <N> A;

int main() {
    rep(i, 0, 5) scanf("%d", &k[i]);
    m = 0;
    rep(i, 0, 5) {
        int base = 1;
        while(k[i] >= base) {
            num[++m] = base * v[i];
            k[i] -= base;
            base *= 2;
        }
        if (k[i] > 0) num[++m] = k[i] * v[i];
    }
    A[0] = 1;
    rep(i, 1, m) A |= (A << num[i]);
    printf("Total=%d\n", A.count() - 1);
    return 0;
}

这几天的吐槽会专门开一篇的

End.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值