BZOJ 1685 [Usaco2005 Oct]Allowance 津贴:贪心【给硬币问题】
题目链接:http://begin.lydsy.com/JudgeOnline/problem.php?id=1333
题意:
有n种不同币值的硬币,并保证大币值一定是小币值的倍数。
每种硬币的币值为val,数量为cnt。
每个月你要给Bessie发金额为c的津贴(可以比c多,但不能少)。
问你最多能发多少个月。
题解:
贪心。
贪心策略:
(1)如果能恰好凑出c的钱,则应尽可能使用大币值的硬币。
(2)如果不能恰好凑出,则应让花的冤枉钱尽可能少。
实现:
先按币值从大到小排序。。。
(1)在保证不花冤枉钱的前提下,尽可能使用大硬币。
(2)如果没凑够c,则再付一个币值最小的硬币。(在第一步之后,再任意给出一个硬币都会使总付出大于c)
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #define MAX_N 25 6 7 using namespace std; 8 9 struct Coin 10 { 11 int val; 12 int cnt; 13 Coin(int _val,int _cnt) 14 { 15 val=_val; 16 cnt=_cnt; 17 } 18 Coin(){} 19 friend bool operator < (const Coin &a,const Coin &b) 20 { 21 return a.val>b.val; 22 } 23 }; 24 25 int n,c; 26 int ans=0; 27 Coin coin[MAX_N]; 28 29 bool pay() 30 { 31 int rest=c; 32 for(int i=0;i<n;i++) 33 { 34 int temp=min(coin[i].cnt,rest/coin[i].val); 35 coin[i].cnt-=temp; 36 rest-=temp*coin[i].val; 37 } 38 if(rest==0) return true; 39 for(int i=n-1;i>=0;i--) 40 { 41 if(coin[i].cnt!=0) 42 { 43 coin[i].cnt--; 44 return true; 45 } 46 } 47 return false; 48 } 49 50 int main() 51 { 52 cin>>n>>c; 53 for(int i=0;i<n;i++) 54 { 55 cin>>coin[i].val>>coin[i].cnt; 56 } 57 sort(coin,coin+n); 58 while(pay()) ans++; 59 cout<<ans<<endl; 60 }