测评会员优惠活动进行中 · 开通 VIP,有效期内测评不限次 VIP 优惠中 · 测评不限次 立即查看

A39811. 邮票收集

填空题 较难

题目描述

邮票收集

题目描述

小A是个邮票收集爱好家,他有n种面值的邮票,每种邮票都有无数张。一天小B想要寄信,需要一共面值和为k的邮票组合。小A想要知道拼出面值为k的邮票最少需要多少张。

输入

输入是多组数据。(不超过10组) 每组数据的第一行正整数n,k,表示邮票的种类数目和目标要拼出的钱。(0 < n ≤ 100, 0 < k ≤ 1000 ) 接下来的一行有n个正整数ai(0 < ai ≤ 1000)。 若n=k=0表示输入结束。

输出

每组数据输出一行一个数,分别表示拼出k需要的最少的邮票数量。 如果不存在能够拼出k的方案,输出-1。

样例输入

4 10

1 2 3 4

5 16

1 2 3 4 5

2 7

4 5

0 0

样例输出

3

4

-1

提示

第一组数据: 10 = 4+4+2 

第二组数据:16 = 5+5+5+1 

第三组数据: 不存在。

参考答案

#include <bits/stdc++.h> using namespace std; int n, k; int a[1010], f[1010]; int main() { // 不知道多少组输入,所以死循环 while(1) { cin >> n >> k; // 都等于0表示输入结束,退出循环 if(n == 0 and k == 0) { break; } // 初始化 f 数组所有数字为大整数。 memset(f, 127, sizeof(f)); // 预处理 0 元需要 0 张邮票 f[0] = 0; for(int i = 1; i <= n; i++) { cin >> a[i]; } // 预处理 a 数组从小到大排序 sort(a + 1, a + n + 1); // 从 1 元开始递推到 k 元 for(int i = 1; i <= k; i++) { // 循环查找 a[1], a[2], a[3]... 等金额不大于 i 元的邮票,找最小值 for(int j = 1; j <= n; j++) { // 因为是从小到大排序的,如果邮票金额大于所需金额,直接退出循环 if(a[j] > i) { break; } // 递推 i 元最少需要多少张邮票 f[i] = min(f[i], f[i - a[j]] + 1); } } // 如果 k 元还是那个最大值,说明已有金额不能组合出 k 元,设为-1 if(f[k] >= (1 << 30)) { f[k] = -1; } cout << f[k] << "\n"; } return 0; }
上一题 下一题