• poj-3040 Allowance (贪心)


    http://poj.org/problem?id=3040

    FJ 有n种不同面值的硬币,每种硬币都有相应的个数,大面值的硬币值总能被小面值的硬币值整除,每周需要支付 Bessie   c元,问最多能支付Bessie多少周。

    这题之所以能贪心,据说关键是这句话 where each denomination of coin evenly divides the next-larger denomination。

    如果没有这个限制条件,有些情况是取不到最优解的。

    把面值从小到大排序,然后从尾到头开始扫,能给多少就给多少,如果面值不够,就从头到尾扫,尽量取刚好超过数额的。

    参考了别人代码,感觉写的很精妙。自己的水平还很欠缺。

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cmath>
     4 #include <vector>
     5 #include <cstring>
     6 #include <string>
     7 #include <algorithm>
     8 #include <string>
     9 #include <set>
    10 #include <functional>
    11 #include <numeric>
    12 #include <sstream>
    13 #include <stack>
    14 #include <map>
    15 #include <queue>
    16 
    17 #define CL(arr, val)    memset(arr, val, sizeof(arr))
    18 
    19 #define ll long long
    20 #define inf 0x7f7f7f7f
    21 #define lc l,m,rt<<1
    22 #define rc m + 1,r,rt<<1|1
    23 #define pi acos(-1.0)
    24 
    25 #define L(x)    (x) << 1
    26 #define R(x)    (x) << 1 | 1
    27 #define MID(l, r)   (l + r) >> 1
    28 #define Min(x, y)   (x) < (y) ? (x) : (y)
    29 #define Max(x, y)   (x) < (y) ? (y) : (x)
    30 #define E(x)        (1 << (x))
    31 #define iabs(x)     (x) < 0 ? -(x) : (x)
    32 #define OUT(x)  printf("%I64d
    ", x)
    33 #define lowbit(x)   (x)&(-x)
    34 #define Read()  freopen("a.txt", "r", stdin)
    35 #define Write() freopen("b.txt", "w", stdout);
    36 #define maxn 1000000000
    37 #define N 100010
    38 using namespace std;
    39 
    40 pair<int,int>p[25];
    41 int use[25];
    42 int main()
    43 {
    44     int n,c,sum;
    45     scanf("%d%d",&n,&c);
    46     sum=0;
    47     for(int i=0;i<n;i++)   scanf("%d%d",&p[i].first,&p[i].second);
    48     sort(p,p+n);
    49     for(int i=0;i<n;i++)  //从大面值  开始 如果面值 大于c 那么直接累加。
    50         if(p[i].first>=c)
    51         {
    52             sum+=p[i].second;
    53             p[i].second=0;
    54         }
    55     while(true)  //不断循环,直到不能在支付为止。
    56     {
    57         int tmp=c;
    58         int flag=0;
    59         memset(use,0,sizeof(use)); //记录每个面值的硬币使用了多少。
    60         for(int i=n-1;i>=0;i--)  //从大面值开始扫。
    61         {    //注意这里只有一次循环,就把所有面值的使用情况扫出来了,因为如果不能用当前面值支付的话 k会变成0,并且要么会刚好支付完,要么tmp>0
    62             if(p[i].second) //当前面值还有                                           不会出现浪费当前面值的情况
    63             {
    64                 int k=tmp/p[i].first;  //为了支付c元 当前面值最多可以用多少个,
    65                 int mi=min(k,p[i].second); //取最小值
    66                 tmp-=p[i].first*mi; //剩下 这么多
    67                 use[i]=mi; //记录使用数量
    68                 if(tmp<=0) {flag=1;break;} //tmp小于0  那么本次支付已结束
    69             }
    70         }
    71         if(tmp>0)  //否则从小到大开始 给
    72         {
    73             for(int i=0;i<n;i++)
    74             {
    75                 if(p[i].second>use[i])  //如果没使用完
    76                 {
    77                     while(use[i]<p[i].second)  //一直使用,因为当前用的面值是最小的那么这样也是最优的。
    78                     {
    79                         tmp-=p[i].first;
    80                         use[i]++;
    81                         if(tmp<=0) {flag=1;break;}
    82                     }
    83                     if(tmp<=0&&flag==1) break; //只有  flag==1的时候 tmp<=0
    84                 }
    85             }
    86         }
    87         if(!flag) break; //已经不能完成支付
    88         int mx=maxn;
    89         for(int i=n-1;i>=0;i--) if(use[i]) mx=min(p[i].second/use[i],mx);  //use[i]是一次支付时当前面值使用的情况,那么p[i].second/use[i] 就表示可以支付 这么多次,并且取的是所有当中的最小值。
    90         sum+=mx;
    91         for(int i=n-1;i>=0;i--) if(use[i]) p[i].second-=mx*use[i]; //取用了 mx次,所以相应数量减少这么多,这样会节省很多时间,不用每次重复计算,是一次很大的优化
    92     }
    93     printf("%d
    ",sum);
    94     return 0;
    95 }
  • 相关阅读:
    uva 11275 3D Triangles (3D-Geometry)
    uva 12296 Pieces and Discs (Geometry)
    poj 1514 Metal Cutting (dfs+多边形切割)
    poj 1474 Video Surveillance (半平面交)
    poj 3335 Rotating Scoreboard (Half Plane Intersection)
    poj 2451 Uyuw's Concert (半平面交)
    poj 1279 Art Gallery (Half Plane Intersection)
    hdu 1255 覆盖的面积 (Bruceforce)
    # WinForm关闭窗体确认
    List<T>随机返回一个
  • 原文地址:https://www.cnblogs.com/nowandforever/p/4425858.html
Copyright © 2020-2023  润新知