原题链接
题目描述
你就要去购物了,现在你手上有N种不同面值的硬币,每种硬币有无限多个。为了方便购物,你希望带尽量少的硬币,但要能组合出1到X之间的任意值。
输入格式
第一行两个数X、N,以下N个数,表示每种硬币的面值。
输出格式
最少需要携带的硬币个数,如果无解输出-1.
样例输入
20 4
1 2 5 10
输出
5
【数据规模】
对于30%的数据,满足N≤3,X≤20;
对于100%的数据,满足N≤10,X≤1000.
起初没想到是贪心,用深搜做的,wa了好几次…还一个就是受之前做过的一道题的影响,总觉得思路差不多,谁知全然不同…
思路:先将所有的面值按升序排列,之后从1开始往上枚举,如果现在的钱数不够了,就加上一个能加的(面值小于等于当前所需钱数)最大面值。注意是最大面值。这样就能保证该面值钱数能用尽可能多的时间。还一个要注意的是,如果排过序的面值最小不是1,那肯定无解,比如最小是2,那么1就无法表示。
code:
#include<bits/stdc++.h>
using namespace std;
int x,n,a[12],cnt,sum;
int main(){
cin>>x>>n;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
if(a[1]!=1){
cout<<-1;
return 0;
}
int j=0,i=0,k; //i表示当前的钱数,j表示指向的面值。
while(i<x)
{
i++;
if(j+1<=n&&a[j+1]<=i&&sum<i) //当前的钱数比后面一个的面值大且当前所拥有的不够用
{
for(k=j+1;k<=n;k++){ //往后寻找比当前钱数小的最大面值
if(a[k]>i) break;
}
j=k-1,sum+=a[j],cnt++;
}
else if(sum<i) sum+=a[j],cnt++; //否则,就加上最大的能加的
//cout<<i<<" "<<sum<<" "<<cnt<<endl;
}
cout<<cnt;
return 0;
}
今天比赛做到两个贪心题,思考的时间都不短,得专题训练!