bzoj:1685 [Usaco2005 Oct]Allowance 津贴
Description
As a reward for record milk production, Farmer John has decided to start paying Bessie the cow a small weekly allowance. FJ has a set of coins in N (1 <= N <= 20) different denominations, where each denomination of coin evenly divides the next-larger denomination (e.g., 1 cent coins, 5 cent coins, 10 cent coins, and 50 cent coins). Using the given set of coins, he would like to pay Bessie at least some given amount of money C (1 <= C <= 100,000,000) every week. Please help him compute the maximum number of weeks he can pay Bessie.
作为对勤勤恳恳工作的贝茜的奖励,约翰已经决定开始支付贝茜一个小的每周津贴. 约翰有n(1≤N≤20)种币值的硬币,面值小的硬币总能整除面值较大的硬币.比如说,币值有如下几种:1美分,5美分,10美分,50美分…..
利用给定的这些硬币,他将要每周付给贝茜一定金额的津贴C(1≤C≤10^8).
请帮他计算出他最多能给贝茜发几周的津贴.
Input
第1行:2个用空格隔开的整数n和C.
第2到n+1行:每行两个整数表示一种币值的硬币.第一个整数V(I≤y≤10^8),表示币值.
第二个整数B(1≤B≤10^6),表示约翰拥有的这种硬币的个数.
Output
一个整数,表示约翰付给贝茜津贴得最多的周数.
Sample Input
3 6
10 1
1 1 00
5 1 20
10 1
1 1 00
5 1 20
Sample Output
111
样例说明
约翰想要每周付给贝茜6美分.他有1个10美分的硬币、100个1美分的硬币、120个5美分的硬币.约翰可以第一周付给贝茜一个10美分的硬币,接着的10周每周付给贝茜2个5芙分硬币,接下来的100周每周付给贝茜一个1美分的硬币和1个5美分的硬币.共计111周.
样例说明
约翰想要每周付给贝茜6美分.他有1个10美分的硬币、100个1美分的硬币、120个5美分的硬币.约翰可以第一周付给贝茜一个10美分的硬币,接着的10周每周付给贝茜2个5芙分硬币,接下来的100周每周付给贝茜一个1美分的硬币和1个5美分的硬币.共计111周.
贪心每次从最大的硬币拿,能拿多少拿多少,最后还不够就找个最小的硬币扔上去。由于数据实在太水,不开long long都可以过……
#include<cstdio> #include<algorithm> using namespace std; struct na{ int v,l; }; int n,m,pos[20]; na o[20]; int ans=0; bool cmp(na a,na b){ return a.v>b.v; } int main(){ scanf("%d%d",&n,&m); for (int i=0;i<n;i++){ scanf("%d%d",&o[i].v,&o[i].l); if (o[i].v>=m) ans+=o[i].l,i--,n--; } sort(o,o+n,cmp); int k,num; do{ k=0;num=1e7; for (int i=0;i<n;i++) if (o[i].l){ int xx=min((m-k)/o[i].v,o[i].l); k+=xx*o[i].v; if (xx!=0) num=min(num,o[i].l/xx); pos[i]=xx; }else pos[i]=0; if (k<m) for (int i=n-1;i>=0;i--) if (o[i].l&&o[i].v>=m-k){ pos[i]++; num=min(num,o[i].l/pos[i]); k+=o[i].v; n=i+1; break; } if (k<m) break; ans+=num; for (int i=0;i<n;i++) o[i].l-=num*pos[i]; }while(num); printf("%d\n",ans); }