【POJ】3040

来源:互联网 发布:微拍网站源码带采集 编辑:程序博客网 时间:2024/06/05 00:27

http://poj.org/problem?id=3040

给奶牛发工资,每周至少 C 元。有面值V_i的硬币B_i个。
求最多能发几周?

贪心。分三个阶段:

(1)首先面额>=C的硬币直接发掉。

(2)对硬币面额从大到小尽量凑到接近C,且不超过C。

(3)按硬币面额从小到大尽量凑到接近C,允许大于C。

重复(2)(3)直到没有解。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <queue>#include <algorithm>using namespace std;int n,c;int ans=0;struct Node{    int val;    int num;}a[30];int use[30];bool cmp(Node a,Node b){    return a.val<b.val;}int main(){    cin >> n >> c;    for (int i=0;i<n;i++){        scanf("%d %d",&a[i].val,&a[i].num);    }    sort(a,a+n,cmp);    for (int i=n-1;i>=0;i--){    // 步骤(1)        if (a[i].val>=c){            ans+=a[i].num;            a[i].num=0;        }    }    while (1){        int Min;        bool flag=false;        int sum=c;        memset(use,0,sizeof(use));        for (int i=n-1;i>=0;i--){        //步骤(2)            if (a[i].num>0){                use[i]=min(sum/a[i].val,a[i].num);                sum-=use[i]*a[i].val;                if (sum==0){                    flag=1;                    break;                }            }        }        if (sum>0){        //步骤(3)            for (int i=0;i<n;i++){                if(a[i].num-use[i]>0){                    while (use[i]<a[i].num){                        sum-=a[i].val;                        use[i]++;                        if (sum<=0){                            flag=1;                            break;                        }                    }                }                if (flag){                    break;                }            }        }        if (!flag){            break;        }        Min=9999999;        for (int i=0;i<n;i++){            if (use[i]>0){                Min=min(Min,a[i].num/use[i]);            }        }        ans+=Min;        for (int i=0;i<n;i++){            if (use[i]>0){                a[i].num-=Min*use[i];            }        }    }    cout << ans << endl;}
原创粉丝点击