邮票 Stamps(洛谷)

题目描述
给一组 n 枚邮票的面值集合和一个上限 k —— 表示信封上能够贴 k 张邮票。

请求出最大的正整数 m,满足 1 到 m 的面值都可以用不超过 k 张邮票表示出来。

输入格式
输入的第一行是两个整数,分别代表邮票上限 k 和邮票面值数 n。
自第二行起,共有 n 个整数,第 i 个整数代表第 i 种邮票的面值 ai

输出格式
输出一行一个整数代表 m,若 m 不存在请输出 0。

输入样例
5 2
1 3

输出样例
13

样例解释
有 1 分和 3 分的邮票;你最多可以贴 5 张邮票。很容易贴出 1 到 5 分的邮资(用 1 分邮票贴就行了),接下来的邮资也不难:

  • 6 = 3 + 3
  • 7 = 3 + 3 + 1
  • 8 = 3 + 3 + 1 + 1
  • 9 = 3 + 3 + 3
  • 10 = 3 + 3 + 3 + 1
  • 11 = 3 + 3 + 3 + 1 + 1
  • 12 = 3 + 3 + 3 + 3
  • 13 = 3 + 3 + 3 + 3 + 1

然而,使用 5 枚 1 分或者 3 分的邮票根本不可能贴出 14 分的邮资。因此,答案为 13。

数据范围
对于 100% 的数据,保证 1 ≤ k ≤ 200,1 ≤ n ≤ 50,1 ≤ ai ≤ 104


题解
完全背包(优化2.0):

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 55, M = 200 * 1e4 + 10;

int n, k;
int w[N], f[M];

int main()
{
	cin >> k >> n;
	
	for (int i = 1; i <= n; i ++) cin >> w[i];
	
	memset(f, 0x3f, sizeof f);
	
	sort(w + 1, w + 1 + n);
	
	f[0] = 0;
	for (int i = 1; i <= n; i ++)
		for (int j = w[i]; j <= w[i] * k; j ++)
			if(f[j - w[i]] + 1 <= k) f[j] = min(f[j], f[j - w[i]] + 1);
			
	for (int i = 1; i <= M; i ++)
		if(f[i] == 0x3f3f3f3f)
		{
			cout << i - 1 << endl;
			return 0;
		}
} 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值