noip模拟 马云 Mr_H

来源:互联网 发布:cooledit有mac版 编辑:程序博客网 时间:2024/05/22 11:46

题目描述:

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

输入:

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

输出:

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

样例输入:

20 412510

样例输出:

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;            }           }}
原创粉丝点击