P1658 购物
https://www.luogu.com.cn/problem/P1658
涉及知识点:贪心
涉及知识点:贪心
黄色题
思路:
道题的解法可能比较单一吧,然后我看了一下下面的题解,有一些不是那么好懂,说的不是特别特别透,或许我举个例子更多人可以看懂。
我们要明确以下几点:
- 如果我们的给定面值里没有1,那么肯定无解,为什么呢,首先我们就没有办法凑出1来。如果有1呢,只要我们舍得带很多硬币,肯定可以凑出任意面值。
- 我们假设现在我们手中的面值已经可以凑出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; }