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

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

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

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

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

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

 #include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <cstring>
#include <string>
#include <algorithm>
#include <string>
#include <set>
#include <functional>
#include <numeric>
#include <sstream>
#include <stack>
#include <map>
#include <queue> #define CL(arr, val) memset(arr, val, sizeof(arr)) #define ll long long
#define inf 0x7f7f7f7f
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0) #define L(x) (x) << 1
#define R(x) (x) << 1 | 1
#define MID(l, r) (l + r) >> 1
#define Min(x, y) (x) < (y) ? (x) : (y)
#define Max(x, y) (x) < (y) ? (y) : (x)
#define E(x) (1 << (x))
#define iabs(x) (x) < 0 ? -(x) : (x)
#define OUT(x) printf("%I64d\n", x)
#define lowbit(x) (x)&(-x)
#define Read() freopen("a.txt", "r", stdin)
#define Write() freopen("b.txt", "w", stdout);
#define maxn 1000000000
#define N 100010
using namespace std; pair<int,int>p[];
int use[];
int main()
{
int n,c,sum;
scanf("%d%d",&n,&c);
sum=;
for(int i=;i<n;i++) scanf("%d%d",&p[i].first,&p[i].second);
sort(p,p+n);
for(int i=;i<n;i++) //从大面值 开始 如果面值 大于c 那么直接累加。
if(p[i].first>=c)
{
sum+=p[i].second;
p[i].second=;
}
while(true) //不断循环,直到不能在支付为止。
{
int tmp=c;
int flag=;
memset(use,,sizeof(use)); //记录每个面值的硬币使用了多少。
for(int i=n-;i>=;i--) //从大面值开始扫。
{ //注意这里只有一次循环,就把所有面值的使用情况扫出来了,因为如果不能用当前面值支付的话 k会变成0,并且要么会刚好支付完,要么tmp>0
if(p[i].second) //当前面值还有 不会出现浪费当前面值的情况
{
int k=tmp/p[i].first; //为了支付c元 当前面值最多可以用多少个,
int mi=min(k,p[i].second); //取最小值
tmp-=p[i].first*mi; //剩下 这么多
use[i]=mi; //记录使用数量
if(tmp<=) {flag=;break;} //tmp小于0 那么本次支付已结束
}
}
if(tmp>) //否则从小到大开始 给
{
for(int i=;i<n;i++)
{
if(p[i].second>use[i]) //如果没使用完
{
while(use[i]<p[i].second) //一直使用,因为当前用的面值是最小的那么这样也是最优的。
{
tmp-=p[i].first;
use[i]++;
if(tmp<=) {flag=;break;}
}
if(tmp<=&&flag==) break; //只有 flag==1的时候 tmp<=0
}
}
}
if(!flag) break; //已经不能完成支付
int mx=maxn;
for(int i=n-;i>=;i--) if(use[i]) mx=min(p[i].second/use[i],mx); //use[i]是一次支付时当前面值使用的情况,那么p[i].second/use[i] 就表示可以支付 这么多次,并且取的是所有当中的最小值。
sum+=mx;
for(int i=n-;i>=;i--) if(use[i]) p[i].second-=mx*use[i]; //取用了 mx次,所以相应数量减少这么多,这样会节省很多时间,不用每次重复计算,是一次很大的优化
}
printf("%d\n",sum);
return ;
}

poj-3040 Allowance (贪心)的更多相关文章

  1. POJ 3040 Allowance 贪心

    这题目的贪心思路还是有一点细节问题的. 还没有证明,据说是因为题目给的条件是每个价格是比它小的价格的倍数才能这么贪心的. 思路如下: 假设要给奶牛的钱为C 1)从大面值到小面值一次拿钱,能拿多少拿多少 ...

  2. POJ 3040 Allowance【贪心】

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

  3. poj 3040 Allowance

    Allowance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1842   Accepted: 763 Descript ...

  4. 【贪心】Allowance POJ 3040

    题目链接:http://poj.org/problem?id=3040 题目大意:你有n种不同面值的硬币,面值为vi的有bi个."硬币的面额均匀地分配下一个更大的面额",即下一个更 ...

  5. 【POJ - 3040】Allowance(贪心)

    Allowance 原文是English,这里就放Chinese了 Descriptions: 作为创纪录的牛奶生产的奖励,农场主约翰决定开始给Bessie奶牛一个小的每周津贴.FJ有一套硬币N种(1 ...

  6. POJ 3040 贪心

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

  7. Greedy:Allowance(POJ 3040)

    零用钱大作战 题目大意:农夫和牛又搞新花样了,现在农夫想给Bessie每个星期都给一点零用钱,农夫有一堆面值的钱币,并且这个钱币都能被上一个钱币整除(1,5,10,50),并且钱币有一定数量,要你求最 ...

  8. POJ 1456(贪心)

    #include <string.h> #include <iostream> #include <queue> #include <stdio.h> ...

  9. poj -3614 Sunscreen(贪心 + 优先队列)

    http://poj.org/problem?id=3614 有c头奶牛在沙滩上晒太阳,每头奶牛能忍受的阳光强度有一个最大值(max_spf) 和最小值(min_spf),奶牛有L种防晒霜,每种可以固 ...

随机推荐

  1. BZOJ 3511 土地划分

    AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=3511 题目分析: 看上去和前面的人员雇佣以及小M种田都很像. 最小割模型来求最大值,一般都 ...

  2. 【bzoj1003】[ZJOI2006]物流运输

    1003: [ZJOI2006]物流运输 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6331  Solved: 2610[Submit][Stat ...

  3. c++ 遍历ini

    inline void CDLG_SET1::EnumIniFile(LPCTSTR pFilePath, CString strKey) { TCHAR strAppNameTemp[];//所有A ...

  4. 宠物AI(个人觉得有问题)

    //宠物AI流程 .刚开始添加宠物 Monster被动State:EnumMonster被NULL MonsterStat:EnumPet跟随 .附近有怪物就改成攻击模式(相关的收尾工作) void ...

  5. 研究AFIncrementalStore

    一.增量存贮(AFIncrementalStore:NSIncrementalStore)在CoreData中所处位置

  6. URAL题解—不断跟新中

    1014:简单题,忘了0的情况可以是10,== 1219:找呀找规律,满足N*(N-1)/2+1=X;就是1 的情况了

  7. c# 获取mac地址的2种方法

    和大家分享下,互相学习一下吧.第一个获取方法好像获取不到mac地址,我用了第二种方法可以获取到.希望知道的可以说下为什么. 1,首先要添加引用:using System.Management; 2,代 ...

  8. 1234['toString']['length'] 等于啥?

    首先说该题的答案:1 这是我在一问一答上做的一个选择题,题目虽小,但是包含内容很多,很多网友斥责此题操蛋,恶心.其实只要我们细心的去理解,这段代码有很多值得我们记住的知识点. 1.[]的作用 []是j ...

  9. 2014 ACM/ICPC Asia Regional Xi'an Online(HDU 5007 ~ HDU 5017)

    题目链接 A题:(字符串查找,水题) 题意 :输入字符串,如果字符串中包含“ Apple”, “iPhone”, “iPod”, “iPad” 就输出 “MAI MAI MAI!”,如果出现 “Son ...

  10. House Robber II

    https://leetcode.com/problems/house-robber-ii/ Note: This is an extension of House Robber. After rob ...