noip模拟 马云 Mr_H

题目描述:

    因讨厌马云而彻底放弃网购,他的日常用品都要到商场去购买,而且必须付现金。但是现金购买,经常会遇到找零的问题,那么现在请你帮助他解决这样一个问题:现在 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
#include
#include
#include
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模拟 马云 Mr_H)