[USACO09OCT] Allowance G - 贪心

给定 \(n\leq 20\) 种不同的硬币面额,每种有一定的数量。每个月要用硬币交租 \(C\) 元,可以超额,问最多能交多少个月。

Solution

贪心。首先尽可能找一种浪费最小的模式。然后尽可能多地按照这种模式交钱。

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 25;

int n,c,v[N],b[N],a[N],ans;

signed main() {
    ios::sync_with_stdio(false);
    cin>>n>>c;
    for(int i=1;i<=n;i++) cin>>v[i]>>b[i];
    for(int i=1;i<=n;i++)
        for(int j=1;j<i;j++)
            if(v[i]<v[j]) swap(v[i],v[j]),swap(b[i],b[j]);
    while(true) {
        int tmp=0;
        memset(a,0,sizeof a);
        for(int i=n;i;--i) {
            a[i]=min((c-tmp)/v[i],b[i]);
            tmp+=a[i]*v[i];
        }
        for(int i=1;i<=n&&tmp<c;i++) {
            int old = a[i]*v[i];
            a[i]+=min((c-tmp-1)/v[i]+1,b[i]-a[i]);
            tmp+=a[i]*v[i]-old;
        }
        if(tmp<c) break;
        int mul=0;
        for(int i=1;i<=n;i++) if(a[i]) mul=1e9;
        for(int i=1;i<=n;i++) if(a[i]) mul=min(mul,b[i]/a[i]);
        if(mul==0) break;
        ans+=mul;
        for(int i=1;i<=n;i++) b[i]-=mul*a[i];
    }
    cout<<ans;
}

猜你喜欢

转载自www.cnblogs.com/mollnn/p/12503367.html