您的位置:首页 > 其它

【2015の复活】砝码称重v2

2015-10-18 21:10 225 查看

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,22…2ki,pi

每次更新bitset即为A|=A<<ci∗a′i

统计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.

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: