给定 (nleq 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;
}