大致题意:有1到N种硬币,第i种硬币的数量为Bi、价值Vi;Farmer John每周要给他的奶牛发至少价值为C的补贴;问利用前面的N种硬币,最多可以给他的奶牛发多少周的补贴?  这是道贪心的题应该不难察觉出来,下面就说下这里贪心的方法: 既然每周发的钱是至少为C,那么用上述硬币凑出来的价值必须是>=C的; 因为凑出来的价值很可能总是不能刚好等于C的,所以大部分时候给的都是会比C要大一些的,而为了能让john尽可能多的发多几周补贴,那就得让每次发的补贴中"比C多出的那部分"尽可能的小;这样做即等于 能够节约更多些钱 来为后面当补贴发。

1、将硬币价值从大到小排序。

2、假设前面k种的硬币价值都是大于等于C的,那么这些就直接取(即一周发一个硬币),因为这些是没办法节约的了。

3、那么用k+1种到第N种都是硬币价值小于C的了;就从大到小拿 尽可能的多拿,但不能大于C(即假如第i种硬币所有拿走都还小于C,就把第i种全拿走,然后往后同样方式判断第i+1种硬币, 直至最接近C而又小于C )。

4、如果第3步中拿的价值小于C;那就从第k+1种到第N种硬币中 从小到大拿,也是尽可能的多拿,直到刚好>=C就停止;这样就使得损失为最小了。

5、将这样取钱方式所能出现的次数 加入到计数器(如果直接一周一周的模拟...可能会超时==...), 然后返回第3步。

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<algorithm>
 8 #include<set>
 9 #include<map>
10 #include<vector>
11 #include<queue>
12 #include<stack>
13 #include<utility>
14 #define ll long long
15 #define inf 0x3f3f3f3f
16 using namespace std;
17
18 int n,c;
19 typedef struct node
20 {
21     int v,b;
22 } node;
23 node a[25];
24 bool cmp(node a,node b)
25 {
26     return a.v>b.v;
27 }
28 int cnt;
29 int main()
30 {
31     //freopen("input.txt","r",stdin);
32     scanf("%d%d",&n,&c);
33     for(int i=0; i<n; i++)
34         scanf("%d%d",&a[i].v,&a[i].b);
35     sort(a,a+n,cmp);  //按价值从大到小排序
36     //
37     cnt=0;
38     int i;
39     for(i=0;; i++) // 把大于等于c的先全部发完
40     {
41         if(a[i].v>=c)
42             cnt+=a[i].b;
43         else
44             break;
45     }
46     //经过上面的循环,0到i-1种类的硬币都发完了
47     int need[25]; //标记某一种硬币用了多少个
48     while(true)
49     {
50         memset(need,0,sizeof(need));
51         int sum=c;
52         for(int j=i;j<n;j++)
53         {
54             if(a[j].b&&sum>0)
55             {                //从大到小取,但不能超过c!
56                 need[j]+=min(a[j].b,sum/a[j].v);
57                 sum-=a[j].v*need[j];
58             }
59         }
60         //
61         if(sum>0)
62         {
63             int temp;
64             for(int j=n-1;j>=i;j--)
65             {
66                 if(a[j].b&&sum>0) //如果上面那次取法不够,就从小往大找补替,这样保证是最小损失
67                 {
68                     temp=min(a[j].b-need[j],(sum+a[j].v-1)/a[j].v);
69                     if(temp>0)
70                     {
71                         sum-=temp*a[j].v;
72                         need[j]+=temp;
73                     }
74                 }
75             }
76         }
77         if(sum>0)
78             break; //如果还不够,就直接退出了
79         //
80         int temp=inf;
81         for(int j=i;j<n;j++)
82         {
83             if(need[j])
84             {           //这里取最小的  每次需要的种类的次数; 从而避免用c来每周每周的计算(会超时哒=_=)
85                 temp=min(temp,a[j].b/need[j]);
86             }
87         }
88         cnt+=temp;
89         for(int j=i;j<n;j++)
90         {
91             if(need[j])
92             {           //把用了的硬币删掉
93                 a[j].b-=temp*need[j];
94             }
95         }
96     }
97     printf("%d\n",cnt);
98     return 0;
99 }

转载于:https://www.cnblogs.com/geek1116/p/5672751.html

poj 3040 Allowance相关推荐

  1. POJ 3040 Allowance【贪心】

    POJ 3040 题意: 给奶牛发工资,每周至少 C 元.约翰手头上有面值V_i的硬币B_i个,这些硬币的最小公约数为硬币的最小面值.求最多能发几周? 分析: 贪心策略是使多发的面额最小(最优解).分 ...

  2. poj 3040 Allowance (贪心

    作为创纪录的牛奶生产的奖励,农场主约翰决定开始给Bessie奶牛一个小的每周津贴.FJ有一套硬币N种(1≤N≤20)不同的面额,每枚硬币是所有比他小的硬币面值的倍数,例如1美分硬币.5美分硬币.10美 ...

  3. POJ 3040 Allowance——经典贪心算法题目

    题目链接 题目大意: 约翰要给他的牛贝西发工资,每天不得低于C元,约翰有n种面值的钱币,第i种的面值为v_i,数量有b_i.问这些钱最多给贝西发多少天的工资.注意,每种面值的金钱都是下一种的面值的倍数 ...

  4. POJ 3040 贪心

    贪心好题 ---. 思路: 从大到小凑C 如果不够 再从小到大补满(超过)C //By SiriusRen #include <cstdio> #include <cstring&g ...

  5. 《挑战程序设计竞赛(第2版)》习题册攻略

    本项目来源于GitHub 链接: 项目GitHub链接 1 前言 项目为<挑战程序设计竞赛(第2版)>习题册攻略,已完结.可配合书籍或笔记,系统学习算法. 题量:约200道,代码注释内含详 ...

  6. [SinGuLaRiTy] 贪心题目复习

    [SinGuLaRiTy-1024] Copyright (c) SinGuLaRiTy 2017. All Rights Reserved. [POJ 2709] 颜料 (Painter) 题目描述 ...

  7. 挑战程序设计竞赛(第二章习题总结)

    文章目录 搜索 Curling 2.0(POJ 3009) Meteor Shower(POJ 3669) Smallest Difference(POJ 2718) Hopscotch(POJ 30 ...

  8. 叉姐的魔法训练小结(未完结)

    说起叉姐,这是一个让人ym的上古神犇,欣赏了一波叉姐的vj,上面挂的基础魔法训练对我来说每题都是神题. 每天做一两个,做了几天终于做了好几个题了,现在写一下心得. POJ 2443 这题给你1000个 ...

  9. 贪心算法 poj3040(C语言)

    发放工资问题: 你有一些各种金额的硬币,给你每个月必须支付的金额,可以多付但不能少付,请你输出最多能支付多少周 例子:你有1个10美分的硬币,120个5美分的硬币,100个1美分的硬币,每月要支付6美 ...

最新文章

  1. python单例模式基于__new__方法实现的单例模式(推荐使用,方便)
  2. 【转】解决父容器高度不跟随子元素扩大的问题
  3. 二叉树的基本操作_二叉树的遍历
  4. 【原创】二级指针中在内存中的样子
  5. 跨站脚本攻击(selfxss)笔记(三)
  6. 【second】Flatten Binary Tree to Linked List
  7. Jquery怎么获取select选中项 自定义属性的值
  8. 3399元起!120Hz瞳孔屏+65W超级闪充,一加 8T今日发布
  9. loadView 和 viewDidLoad、viewDidunload 的区别
  10. 计算机共享文件怎样添加,怎么添加另一台电脑的共享文件夹
  11. HDU3785 寻找大富翁【优先队列】
  12. 如何从 ArcView 3.3 版本的工程迁移到 ArcGIS Desktop 10 ?
  13. gitee上贡献度不显示问题的设置
  14. 海尔计算机无法装win7系统,海尔Haier电脑预装win8换win7系统BIOS设置及安装教程
  15. drcom 不耍流氓
  16. 常见对象-String类
  17. hackthebox(HTB) Ambassdor !
  18. 英文商务电邮实用技巧
  19. 2018 世界杯:科技辅助裁判是否靠谱?
  20. 淘金(bzoj 3131)

热门文章

  1. hibernate中List一对多映射关系详解
  2. Android视图绘制流程完全解析,带你一步步深入了解View(二)
  3. 凸包Graham Scan算法实现
  4. Redis源码简要分析
  5. JMP跳转指令的指令长度、直接转移与间接转移、段内跳转与段间跳转
  6. JUC并发编程四 并发架构--并发之共享模型
  7. 常考数据结构与算法-morris遍历
  8. linux三 gdb/makefeile/io
  9. foo、bar到底是什么意思
  10. 面向对象编程基础 (一)