【YbtOJ高效进阶】【完全背包】【DP】货币系统

链接

YbtOJ 货币系统

题目描述

给你一些数字,这堆数字无论哪个数选多少个都可以,然后就会有一些数能凑出,一些不能。
要你再找一堆尽可能少的数字,使得它像前面那样凑能凑出的和不能凑出的是一模一样的。
输出你找的这堆最少个数的数字的个数。

样例输入

2
4
3 19 10 6
5
11 29 13 19 17

样例输出

2
5

思路

完全背包
我们的m一开始设为n,然后找a[i]里有多少可以被表示出来,m随之减小,那么就可以得到最后的答案了
枚举过程中把可以得到的数值标记了

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

int T, n;
int f[10000005], a[10000005];

int main()
{
	scanf("%d", &T);
	for(int t = 1; t <= T; ++t)
	{
		scanf("%d", &n);
		for(int i = 1; i <= n; ++i)
			scanf("%d", &a[i]);
		memset(f, 0, sizeof(f));
		sort(a + 1, a + n + 1);
		f[0] = 1;
		int ans = n;
		for(int i = 1; i <= n; ++i)
		{
			if(f[a[i]]) {
				ans--;
				continue;
			}
			for(int j = a[i]; j <= a[n]; ++j)
				f[j] |= f[j - a[i]];
		}
		printf("%d\n", ans);
	}
	return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值