每日一题:货币系统 (背包dp)

题意

$n$ 种面额货币,数量无限,问最多保留几种,使得原来可以组成的仍然可以组成。($t<=20,n<=100,a[i]<=25000$)

solution

由于大的只会被小的组成,所以先排序,对于存在性问题就显然是完全背包了,dp[i] 表示是否能表示出 $i$ 价值,得到状态转移方程:$dp[i]|=dp[i-a[i]]$,对于已经可以表示出来对 $a[i]$,已经可以由小的组成,因此不需要在枚举。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <bits/stdc++.h>
using namespace std;
int t, n, res, a[105], dp[300005];
int main() {
cin >> t;
while (t--) {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1);
memset(dp, 0, sizeof(dp));
res = 0;
dp[0] = 1;
for (int i = 1; i <= n; i++) {
if (!dp[a[i]]) {
res++;
for (int j = a[i]; j <= a[n]; j++) dp[j] |= dp[j - a[i]];
}
}
cout << res << '\n';
}
return 0;
}
作者

Benboby

发布于

2020-05-29

更新于

2021-01-28

许可协议

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×