Allowance
原文是English,这里就放Chinese了
Descriptions:
作为创纪录的牛奶生产的奖励,农场主约翰决定开始给Bessie奶牛一个小的每周津贴。FJ有一套硬币N种(1≤N≤20)不同的面额,每枚硬币是所有比他小的硬币面值的倍数,例如1美分硬币、5美分硬币、10美分硬币和50美分硬币。使用这些硬币,FJ每周至少给Bessie C(1 <= C <=100000000)美分。请你计算他最多能给Bessie几周
* 第一行N 、 C
* 第 2..N+1行: 硬币价值 V (1 <= V <= 100,000,000) 和数量 B (1 <= B <= 1,000,000)
* 第 2..N+1行: 硬币价值 V (1 <= V <= 100,000,000) 和数量 B (1 <= B <= 1,000,000)
* 使用这些硬币,每周至少给C美分的前提下的最多周数
Sample Output3 6 10 1 1 100 5 120
Hint111
输出提示
FJ给Bessie 10美分一周;给Bessie 5美分和1美分一百周;给Bessie 两枚5美分十周
题目链接:
https://vjudge.net/problem/POJ-3040
题目大意:FJ要发硬币工资给他的奶牛,工资不低于c,他有n个硬币,币值和数目。问你最多发多少个星期
1)从大面值到小面值一次拿钱,能拿多少拿多少。
但是注意不能拿到的钱的总和大于C
2)如果第一步拿到的钱不够C,那么就从小面值到大面值拿钱,能拿多少拿多少。
直到拿到的钱总和大于等于C
AC代码
#include <iostream> #include <cstdio> #include <fstream> #include <algorithm> #include <cmath> #include <deque> #include <vector> #include <queue> #include <string> #include <cstring> #include <map> #include <stack> #include <set> #include <sstream> #define mod 1000000007 #define eps 1e-6 #define ll long long #define INF 0x3f3f3f3f #define ME0(x) memset(x,0,sizeof(x)) using namespace std; pair<int,int> a[25];//硬币面值,数量 int use[25];//这个面值的硬币已经使用了多少 int n,c;//硬币种类,每周最少给多少钱 int main() { cin>>n>>c; for(int i=1; i<=n; i++) cin>>a[i].first>>a[i].second; sort(a+1,a+1+n); int ans=0;//答案 while(true) { ME0(use);//每次都归零 int rest=c;//还有这么多钱没给奶牛 for(int i=n; i>=1; i--)//从大到小 { int tmp=min(rest/a[i].first,a[i].second);//这种类型的硬币能拿几个 rest-=tmp*a[i].first;//还有多少钱没给奶牛 use[i]=tmp;//这种硬币用了几个 } if(rest)//还有钱没有发完 { for(int i=1; i<=n; i++)//从小到大 { if(a[i].second&&a[i].first>=rest)//这种硬币没有花完并且这种硬币的价值大于没有发完的钱 { use[i]++;//这种硬币用了一个 rest=0;//钱全部发给奶牛了 break; } } } if(rest)//钱还没发完,即钱不够了,退出循环 break; int minx=INF; for(int i=1; i<=n; i++)//从小到大 { if(use[i])//这种硬币一周要用几个,可以算出剩余的硬币可以用多少周 minx=min(minx,a[i].second/use[i]); } ans+=minx; for(int i=1; i<=n; i++)//把硬币的数量更新 { if(use[i]) a[i].second-=use[i]*minx; } } cout<<ans<<endl; }