P1658 购物

https://www.luogu.com.cn/problem/P1658
涉及知识点:贪心
黄色题

思路:

道题的解法可能比较单一吧,然后我看了一下下面的题解,有一些不是那么好懂,说的不是特别特别透,或许我举个例子更多人可以看懂。

我们要明确以下几点:

  1. 如果我们的给定面值里没有1,那么肯定无解,为什么呢,首先我们就没有办法凑出1来。如果有1呢,只要我们舍得带很多硬币,肯定可以凑出任意面值。
  2. 我们假设现在我们手中的面值已经可以凑出11~HH中的所有面值,这个时候,我们要想一想,我们现在再准备带的这个硬币,应该满足什么样的条件呢?现在举一个例子。我们手里现在有面值和为5的硬币,并且可以凑出从11~55的所有面值。现在,
如果我们选				则可以凑出
1						1,2,3,4,5,6
2						1,2,3,4,5,6,7
3						1,2,3,4,5,6,7,8
4						1,2,3,4,5,6,7,8,9
5						1,2,3,4,5,6,7,8,9,10
6						1,2,3,4,5,6,7,8,9,10,11
选一个解释:如果我们选4,那我们肯定可以凑出1~5(之前就可以凑出
来),对于6,我们可以用之前凑出来的2加上现在选的4,对于7,我们可以
用之前凑出来的3加上现在选的4,以此类推,但是10我们就不能凑出来了。
然后,如果我们选择7,同理可以凑出来1~5,然后6呢,我们选之前凑不出
来,用现在选的7加上“没有”、“1”、“2”、“3”、“4”、“5”都不
可能凑出来,因为7+0就已经大于6了,再加什么也不可能等于6。你也可以
再去自己算一下其他的例子,会发现,当且仅当我们选的数不大于当前选的
面值的和+1,我们可以保证凑出连续的面值(不要想去跳着凑面值,不可能
的)。
然后我们发现,我们选的数越大,他可以凑出来的面值就越多,我们就尽可
能的选给我们的面值里面,满足不大于面值和+1的最大面值,这样,我们带
去购物且满足可以凑出1~X中所有面值的硬币数会更少,答案就更小。

#include<iostream>
#include<algorithm>
using namespace std;
int a[1005];
bool cmp(int p,int q){
    return p>q;
}//尽量选大的才能保证答案最小
int main()
{
    int X,n,ans=0,SUM=0;
    cin>>X>>n;
    for(int i=1;i<=n;i++)cin>>a[i];
    sort(a+1,a+n+1,cmp);
    if(a[n]!=1){//我们说过了,无解的情况
        cout<<-1<<endl;
        return 0;
    }
    while(SUM<X){//如果我们现在还不能凑出1~X的所有面值,那就要再选
        for(int i=1;i<=n;i++)
            if(a[i]<=SUM+1){
                SUM+=a[i];
                break;
            }
        ans++;//又选了一张
    }
    cout<<ans<<endl;
    return 0;
}

 





posted @ 2022-07-15 15:39  -イレイナ  阅读(34)  评论(0)    收藏  举报