洛谷 - P1658 购物 - 贪心

为了凑出 1 - x 的所有硬币:

假设当前已经凑出了1 ~ m 的所有面值的硬币,那么为了凑出更大面值的硬币,应该如何选择呢?

有这些情况:

<1> 选面值 t 属于 1~m  的硬币:

这当然可以,但是想一想,有没有更好的选择呢?

我们选择一个面值为 t 的硬币,那么,我们下一次能够凑出的面值为 1 ~ m + t

为了符合题意、凑出所有1 ~ x 的硬币,我们当然希望这个 m + t  越大越好!

那么,就要求我们这一次选择的 t 越大越好。

因此: 我们可能需要再 1 ~ m中选一个价值最大的硬币。

<2> 选面值 t 属于 m+1 ~ ? 的硬币:

假设选择面值是 t + 1的,这符合题意吗? 

想一想: 原本凑出了1~m,这一次得到了m+1,那么我们就得到了从 1 ~ 2m + 1的所有面值的硬币。这说明选1 + m是可以的

那么,还能继续变大吗?

比如 选 m+2 ?

显然不行,如果选择了m+2,那么我们就没有办法凑出面值为 m + 1的硬币了(想一想,原本凑出的是1~m的硬币,这一次选了个m+2的硬币,那么我们能凑出的

硬币的区间实际上是不连续的 ,它是 [1 , m]  U [m+2,2m+2] ,漏掉了 m+1 。 )

 

因此,可以确定贪心的方法: 每一次从所有面值中选择一个面值 t 属于 [1,m+1] 的、且最大面值的硬币。

就可以得到最优解

 1 #include <iostream>
 2 #include <algorithm>
 3 using namespace std;
 4 int arr[20];
 5 int main(){
 6     int x,n;
 7     cin >> x >> n;
 8     for(int i = 0; i < n; i++){
 9         cin >> arr[i];
10     }
11     sort(arr,arr+n);
12     
13     int m = 0;
14     int cnt = 0;
15     while(m < x){
16         for(int j = n-1; j >= 0; j--){
17             if(arr[j] <= m+1){
18                 cnt++;
19                 m += arr[j];
20                 break;
21             }
22         }
23     }
24     if(cnt == 0 && x != 0)
25         cout<<"-1";
26     else cout<<cnt;
27     return 0;
28 }
posted @ 2020-01-14 20:16  popozyl  阅读(208)  评论(0编辑  收藏  举报