poj 3040 Allowance

题意:

约翰有一些硬币,这些硬币中的大面值都可以被任何小于它面值的硬币的面值所整除,比如1 5 10 50等。

现在每个面值的硬币有若干个,约翰每周至少要付给他的奶牛的薪酬为C,问约翰最多可以付多少周。

思路:

贪心,一道好题。

首先从大面值的往小面值的加,不能超过C,但是一定要尽量接近C或者等于C。

之后再加最小的面值的一个硬币或者不加就可以凑够C,这个最小的面值是指数量不为0的硬币中面值最小的。

这个贪心原则是正确的,我的一个比较独特的一个证明:

因为每次都是加的面值最小的一个硬币(在从大到小加小于C的情况下),所以可以保证每次超过C的钱是最少的,也就是说浪费的钱是最少的,那么就可以剩下尽可能多的钱再去凑C。

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <vector>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 struct node
  8 {
  9     int val,num;
 10     node(){};
 11     node(int a,int b)
 12     {
 13         val = a;
 14         num = b;
 15     }
 16 };
 17 
 18 vector<node> a;
 19 
 20 bool cmp(node x,node y)
 21 {
 22     return x.val > y.val;
 23 }
 24 
 25 int main()
 26 {
 27     int n,c;
 28     
 29     while (scanf("%d%d",&n,&c) != EOF)
 30     {
 31         a.clear();
 32         
 33         for (int i = 0;i < n;i++)
 34         {
 35             int x,y;
 36             scanf("%d%d",&x,&y);
 37             
 38             a.push_back(node(x,y));
 39         }
 40         
 41         sort(a.begin(),a.end(),cmp);
 42         
 43         long long ans = 0;
 44         
 45         for (int i = 0;i < n;i++)
 46         {
 47             if (a[i].val >= c)
 48             {
 49                 ans += a[i].num;
 50                 a[i].num = 0;
 51             }
 52             else
 53             {
 54                 while (a[i].num > 0)
 55                 {
 56                     long long sum = 0;
 57                     
 58                     for (int j = i;j < n;j++)
 59                     {
 60                         if (a[j].num <= 0) continue;
 61                         
 62                         if (sum + a[j].val > c) continue;
 63                         
 64                         while (1)
 65                         {
 66                             if (sum + a[j].val > c)break;
 67                             
 68                             sum += a[j].val;
 69                             
 70                             a[j].num--;
 71                             
 72                             if (a[j].num <= 0) break;
 73                             
 74                             if (sum == c) break;
 75                         }
 76                     }
 77                     
 78                     if (sum == c) ans++;
 79                     else
 80                     {
 81                         for (int j = n - 1;j >= i;j--)
 82                         {
 83                             if (a[j].num <= 0) continue;
 84                             if (sum >= c) break;
 85                             
 86                             while (1)
 87                             {
 88                                 sum += a[j].val;
 89                                 
 90                                 a[j].num--;
 91                                 
 92                                 if (a[j].num <= 0) break;
 93                                 
 94                                 if (sum >= c) break;
 95                             }
 96                         }
 97                         
 98                         if (sum >= c) ans++;
 99                         else break;
100                     }
101                 }
102             }
103         }
104         
105         printf("%lld\n",ans);
106     }
107     
108     return 0;
109 }

 

posted @ 2018-04-12 15:35  qrfkickit  阅读(172)  评论(0编辑  收藏  举报