| ||||||||||
Online Judge | Problem Set | Authors | Online Contests | User | ||||||
---|---|---|---|---|---|---|---|---|---|---|
Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest |
这个贪心。。。。。。#include<cstdio> //该题是由硬币问题衍生出的更高级的贪心问题 #include<cstring> //硬币选取的方式与之前的一样 #include<algorithm> using namespace std; const long INF=0x3f3f3f; const int MAXN=35; int use[MAXN]; //记录当前取法的第i种面值取的个数 struct Coin{ int b,v; }coin[MAXN]; int cmp(const Coin &a,const Coin &b){ return a.v<b.v; } int main() { int N,C,m; while(scanf("%d%d",&N,&C)!=EOF){ for(int i=0;i<N;i++) scanf("%d%d",&coin[i].v,&coin[i].b); sort(coin,coin+N,cmp); int ans=0; for(int i=N-1;i>=0;i--){ //只要面值大于C的纸币,都可以一次性支付 if(coin[i].v>=C){ ans+=coin[i].b; coin[i].b=0; } } while(true){ //每次循环寻找一个当前最优的走法,直到剩下的总金额小于C int sign=0; //是否找到合适的选取方式的标记 long cnt=C; memset(use,0,sizeof(use)); for(int i=N-1;i>=0;i--){ //第二步,从大到小取,不能超过C的面值 if(coin[i].b){ //可以选择当前纸币 int k=cnt/coin[i].v; m=min(k,coin[i].b); //尽可能地使用大面额的纸币 cnt-=m*coin[i].v; use[i]=m; if(cnt==0){ sign=1;break; //已经找到足够的金币了,直接退出 } } } if(cnt>0){ for(int i=0;i<N;i++){ //从小到大选取 while(coin[i].b>use[i]){ cnt-=coin[i].v; use[i]++; if(cnt<=0){ sign=1;break; } } if(sign)break; } } if(!sign)break; m=INF; for(int i=0;i<N;i++){ if(use[i]) //找到当前取法能取的总次数 m=min(m,coin[i].b/use[i]); } ans+=m; for(int i=0;i<N;i++){ if(use[i]) coin[i].b-=m*use[i]; } } printf("%d\n",ans); } return 0; } Followed by: Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator