您的位置:首页 > 业界新闻

noip模拟 马云 Mr_H

2017-08-29 12:33 162 查看

题目描述:

因讨厌马云而彻底放弃网购,他的日常用品都要到商场去购买,而且必须付现金。但是现金购买,经常会遇到找零的问题,那么现在请你帮助他解决这样一个问题:现在 Mr_he 手上有 n 种不同面值的硬币,每种硬币有无限多个。为了方便购物,他希望带尽量少的硬币,但是要能组合出 1 到 m 之间的任意值。


输入:

第一行为两个整数:m 和 n,他们的意义如题目描述。接下来的 n 行,每行一个整数,第 i+1 行的整数表示第 i 种硬币的面值。


输出:

最少需要携带的硬币数量,如果无解则输出-1。


样例输入:

20 4
1
2
5
10


样例输出:

5


简析:

首先判断有无解,如果最小面额硬币大于1则无解,因为搭配不出1,如果有一则有解,因为所有面额都可以由1堆积出来。
接下来思考一个问题,假设当前硬币可以组合出1到5的任意面额,那么添加一枚面额为6的硬币就可以搭配出1到11的任意面额,于是我们依照这个思路,假设当前硬币面值的和为sum,每一次添加硬币时,从大到小搜索,将搜索到的第一枚面值小于等于sum+1的硬币加入,(sum+1是上限),并将计数器+1,更新sum值。


代码:

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
int a[1100];
int main(){
int n,m;
scanf("%d%d",&m,&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);  //注意排序
if(a[1]!=1){
printf("-1");
return 0;
}
int sum=0,ans=0;
while(1){
if(sum>=m){
printf("%d",ans);
return 0;
}
for(int i=n;i>=1;i--)   //从大到小
if(a[i]<=sum+1){
sum+=a[i];
ans++;
break;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  noip模拟 马云 递推