题目链接:https://www.luogu.com.cn/problem/P1658
题目描述
你就要去购物了,现在你手上有N种不同面值的硬币,每种硬币有无限多个。为了方便购物,你希望带尽量少的硬币,但要能组合出1到X之间的任意值。
输入格式
第一行两个数X、N,以下N个数,表示每种硬币的面值。
【数据规模】
对于30%的数据,满足N≤3,X≤20;
对于100%的数据,满足N≤10,X≤1000.
输出格式
最少需要携带的硬币个数,如果无解输出-1.
输入输出样例
输入 #1
20 4
1 2 5 10
输出 #1
5
//题意:给定一定面值的钱,让你能凑够1-X中的所有值的同时,硬币数最少
//思路:首先必须得有1,否则凑不到1,就无解了;维护一个变量now,表示我们目前能凑够1~now之间的所有钱数,如果now >= X,就可以得到答案了;否则的话,就找到一个硬币的面值k,使得k是不超过now + 1的最大硬币面值。循环执行即可!
//举个简单的例子:假如now = 8, 那么我就能取到1~8中得所有钱,那么我下一次取的硬币面值不能超过9;因为假如我取了个10,那么我无法凑9元的。而如果我取了个9, 那么因为我前面能取到1~8中的所有,那么我现在就能取到[1, 8] ∪ 9 ∪ [ (1 + 9) ,(8 + 9)] 也就是 [1, 17]; 如果我取了个8, 那么只能凑够[1, 16];显而易见是取9更好;所以取不超过(当前总面值数 + 1)的最大值
//代码:
//#include<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cmath>
using namespace std;
typedef long long ll;
const int INF = 0x3fffffff;
const int N = 15;
int w[N];
int main() {
int x, n;
cin >> x >> n;
for (int i = 0; i < n; i++)
cin >> w[i];
sort(w, w + n); //排序
if (w[0] != 1) cout << -1 << endl; //如果没有1,就无解
else {
int ans = 0, now = 0; //now是当前凑够的总钱数
while (now < x) {
for (int i = n - 1; i >= 0; i--) //从大到小找满足条件的(就是第一次找到的)
if (w[i] <= now + 1) {
now += w[i];
break;
}
ans++;
}
cout << ans << endl;
}
return 0;
}