NC21228 货币系统(5月27日 完全背包)

NC21228 货币系统

题目链接

题目大意
给出一个包含 n n n 个不同面值的货币系统,最少要多少种货币能表示出原货币系统能表示的所有面额。

输入
2
4
3 19 10 6
5
11 29 13 19 17
输出
2
5
说明
在第一组数据中,货币系统(2, [3,10])和给出的货币系统(n, a)等价,并可以验证不存在m < 2的等价的货币系统,因此答案为2。
在第二组数据中,可以验证不存在m < n的等价的货币系统,因此答案为5。
备注:
1 <= T <= 20, 1 <= n <= 100, 1 <= a[i] <= 25000

分析:
我们可以把这个货币系统能表示出的所有面额都求出来,从这些面额中选取一部分,如果同样能把所有面额都表示出来,那么就是与原货币系统等价的。再想,那些不在货币系统中的面额都是从中被表示出来的,这些就是多余的,不能选它们,那么同样货币系统中的那些可以由其它货币表示出来的也不能选。所以,最后问题就变成了在货币系统中哪些数能被其它数组成,剩下的数就是最小集合,货币无限次,这就是完全背包, f [ i ] f[i] f[i] 表示能否组成 i i i ,如果等于1表示可以,如果等于0表示不能组成,就记录到答案中。

Code:

// https://ac.nowcoder.com/acm/problem/21228
#include <bits/stdc++.h>
using namespace std;
int a[110];
bool dp[25010]; //完全背包,大的币能否被小的币表示出
int main() {
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> a[i];
        sort(a + 1, a + n + 1);
        memset(dp, 0, sizeof(dp));
        dp[0] = 1;
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            if (dp[a[i]]) continue;
            ans++;
            for (int j = a[i]; j <= 25000; j++)
                dp[j] |= dp[j - a[i]];
        }
        cout << ans << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值