我是靠谱客的博主 彪壮小蝴蝶,最近开发中收集的这篇文章主要介绍P1658 购物(贪心算法),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

P1658 购物
提交 2.48k
通过 1.16k
时间限制 1.00s
内存限制 125.00MB
题目描述

你就要去购物了,现在你手上有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
题目链接:https://www.luogu.com.cn/problem/P1658
1.首先我们要判断数组内是否存在1,因为面额1只有1可以组成,而且如果存在面值1的硬币,是一定可以组成出1-x的面值。
2.每次尽量用最大面值硬币组合,这样子才可以组成出最小的携带数。因此用sort排序。
上样例分析:

第一次取1:
reach=1;当前可以组成的面额值
第二次取2:1,2,3
观察:3是利用1+2得出的,如果我们当前可以取到的面额为reach,那么我们再携带的一个硬币a[i],1–reach+a[i]都是可以组合出来的,因为2可以和1–reach的面值任意组合都是可行的所以reach更新为reach+=a[i];reach为3
第三次取2:1,2,3,4,5
与上同理reach为5

#include<iostream>
#include<cstdio>
#include<algorithm>
#define INF 0x3f3f3f3f
#define ll long long
#define speed(x) ios::sync_with_stdio(false), cin.tie(x), cout.tie(x)
#define bug(x) cout << #x << " == " << x << 'n';
const ll int MAX_N = 5e5 + 5;
using namespace std;
const int Maxn=1005;
int a[MAX_N]={0};
int main()
{
   int n,x;
   cin>>x>>n;

   for(int i=1;i<=n;i++)
    scanf("%d",&a[i]);

    sort(a+1,a+n+1);

    if(a[1]!=1)//需要可以组合出1-x的面值,而面值1只有1本身可以组合,
    {
        cout<<-1<<'n';//而且如果有面值1无论后面的面值是怎么样的,都可以组合出1-x的面值例:1 1 1 1 1 .....
        return 0;
    }
    int reach=0;//可以组成的面额值
    int ans=0;
    while(reach<x)
    {
        int i=n;
        for(;i>=1;i--)//尽量找最大的
        {
            if(a[i]<=reach+1)
                break;
        }//1~reach面额的钱都可以组成,所以只需要找最大面额的钞票,
        //该钞票可以和reach+1-a[i]的钱组成reach+1或者直接等于reach+1
        reach+=a[i];//a[i]可以和reach+1-a[i]组成reach+1,同理a[i]可以和reach+2-a[i](reach+2-a[i]<=reach即可)组成reach+2....
        ans++;//携带的钞票增加1个;
    }
    printf("%dn",ans);
    return 0;
}

最后

以上就是彪壮小蝴蝶为你收集整理的P1658 购物(贪心算法)的全部内容,希望文章能够帮你解决P1658 购物(贪心算法)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(64)

评论列表共有 0 条评论

立即
投稿
返回
顶部