Allowance POJ 3040(贪心)

原题

题目链接

题目分析

有点难码的贪心题,策略是先能用大面额的就用大面额,然后凑出的价格不要高于c,如果凑到最后不能刚好凑完c,则能用小面额补就用小面额补,目的是让凑出的价格尽可能接近c,这样能少浪费钱,具体实现就是先从现有硬币里按照上述规则找一套凑法,然后不断用这个凑法凑直到硬币不足为止,接着又从剩下的硬币中选出一种凑法继续同样的操作.注意有一点可以优化,如果有面额大于c的货币,直接统计到答案中,因为不需要凑.

代码

 1 #include <cstdio>
 2 #include <cstdlib>
 3 #include <iostream>
 4 #include <algorithm>
 5 #include <utility>
 6 #include <ctime>
 7 #include <cmath>
 8 #include <cstring>
 9 #include <string>
10 #include <stack>
11 #include <queue>
12 #include <vector>
13 #include <set>
14 #include <map>
15 
16 using namespace std;
17 typedef long long LL;
18 const int INF_INT=0x3f3f3f3f;
19 const LL INF_LL=0x3f3f3f3f3f3f3f3f;
20 
21 typedef pair<int,int> P;
22 int N,C;
23 P coin[20];
24 int cnt;
25 int ans;
26 
27 void solve()
28 {
29     for(int i=cnt-1;i>=0;i--)
30     {
31         while(coin[i].second)
32         {
33             int cost[20],rest=C;
34             for(int j=0;j<cnt;j++) cost[j]=0;
35             int k=i;
36             while(rest>0&&k>=0)
37             {
38                 while(coin[k].second&&rest>=coin[k].first) rest-=coin[k].first,coin[k].second--,cost[k]++;
39                 k--;
40             }
41             k=0;
42             while(rest>0&&k<=i)
43             {
44                 while(coin[k].second&&rest>0) rest-=coin[k].first,coin[k].second--,cost[k]++;
45                 k++;
46             }
47             if(rest>0) return;
48             else
49             {
50                 ans++;
51                 int minn=INF_INT;
52                 for(int j=0;j<cnt;j++)
53                     if(cost[j]) minn=min(minn,coin[j].second/cost[j]);
54                 ans+=minn;
55                 for(int j=0;j<cnt;j++)
56                     if(cost[j]) coin[j].second-=minn*cost[j];
57             }
58             /*
59             printf("ans=%d\n",ans);
60             for(int j=0;j<cnt;j++)
61             printf("%d   %d\n",coin[j].first,coin[j].second);*/
62         }
63     }
64     return ;
65 }
66 
67 int main()
68 {
69 //    freopen("black.in","r",stdin);
70 //    freopen("black.out","w",stdout);
71     scanf("%d %d",&N,&C);
72 
73     for(int i=0;i<N;i++)
74     {
75         int x,y;
76         scanf("%d %d",&x,&y);
77         if(x>=C) ans+=y;
78         else coin[cnt].first=x,coin[cnt++].second=y;
79     }
80     sort(coin,coin+cnt);
81     solve();
82     cout<<ans<<endl;
83     return 0;
84 }

 

posted @ 2019-08-24 15:01  VBL  阅读(201)  评论(0编辑  收藏  举报