洛谷 - 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 }
---- suffer now and live the rest of your life as a champion ----