zoukankan      html  css  js  c++  java
  • poj 3040 Allowance (贪心

         作为创纪录的牛奶生产的奖励,农场主约翰决定开始给Bessie奶牛一个小的每周津贴。FJ有一套硬币N种(1≤N≤20)不同的面额,每枚硬币是所有比他小的硬币面值的倍数,例如1美分硬币、5美分硬币、10美分硬币和50美分硬币。使用这些硬币,FJ每周至少给Bessie C(1 <= C <=100000000)美分。请你计算他最多能给Bessie几周 
    Input
        * 第一行N 、 C
    
        * 第 2..N+1行: 硬币价值 V (1 <= V <= 100,000,000) 和数量 B (1 <= B <= 1,000,000) 
    Output
        * 使用这些硬币,每周至少给C美分的前提下的最多周数 
    Sample Input
    
        3 6
        10 1
        1 100
        5 120
    
    Sample Output
    
        111

    此题贪心情况有三个:

    1. 对于硬币面值大于c的,贪心情况是不搭配别的一次只发一个损失最小,先把这些发完

    2. 对于可以凑成c的硬币搭配,参与组合的硬币面值越大,所用的硬币越少,剩下的硬币搭配的可能性更多,先把这些发完

    3. 对于1.2情况处理后,用处理2的思路找出最接近c的硬币搭配,再从小到大找最后一枚硬币(已用2的思路贪心处理过了,结果已尽可能接近c而不到c,最后一枚参与的硬币越小,损失约越小)

    注意2.3贪心情况的实现,凑c的循环可共同利用

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int inf=0x3f3f3f3f;
    struct node{
         int x,n;
         int m,mn;
         bool operator < (const node &rsh) const{
             return x<rsh.x;
         }
    }a[30];
    int main(){
         int n,c,ans=0;
         scanf("%d%d",&n,&c);
         for(int i=0 ; i<n ; i++)scanf("%d%d",&a[i].x,&a[i].n),a[i].m=0;
         sort(a,a+n);
    
             for(int i=n-1 ; i>=0 ; i--){                     //大于c的硬币
                 if(a[i].x>=c&&a[i].n>0)
                    ans+=a[i].n,a[i].n=0;
             }
             int flag=1;
         while(flag){
    
                int mm=c,mn=inf;
                for(int i=n-1 ; i>=0 ; i--){                 //从大到小尽力填充
                        a[i].m=0;
                    if(a[i].n){
                        a[i].m=min(a[i].n,mm/a[i].x);
                        mm-=a[i].m*a[i].x;
                    }
                    if(mm==0)break;
                }
                if(mm>0){                                             //填充不了正好c,但此时就算是最小的硬币也尽力填充了,决定是否大于c的只是最后的  一 枚硬币
                     for(int i=0 ; i<n ; i++){                  //用面值最小的硬笔开始填充,损失最小的贪心选择
                         if(a[i].x>mm&&(a[i].n-a[i].m)){
                             a[i].m++;
                             mm-=a[i].x;
                             break;
                         }
                     }
                }
                if(mm>0)break;
                for(int i=0 ; i<n ; i++)if(a[i].m)mn=min(mn,a[i].n/a[i].m);
                ans+=mn;
                for(int i=0 ; i<n ; i++)if(a[i].m)a[i].n-=mn*a[i].m;
             }
         //for(int i=0 ; i<n ; i++)printf("%d %d
    ",a[i].x,a[i].n);
        printf("%d",ans);
         return 0;
    }
  • 相关阅读:
    各类运算符练习
    用if语句把24小时制转换成12小时制
    Android课程---优化ListView列表视图
    Android课程---关于ListView列表视图的学习
    Android课程---时间日期对话框
    Android课程---关于对话框的学习
    Android课程---用进度条改变图片透明度
    Android课程---进度条及菜单的学习
    Android课程---final关键字
    Android课程---日历选择器和时间选择器
  • 原文地址:https://www.cnblogs.com/-ifrush/p/10527651.html
Copyright © 2011-2022 走看看