P2376 [USACO09OCT]Allowance G
显然的贪心思路就是尽可能的不浪费,
那么就首先从前往后扫,把能拿且不浪费的大的都拿到
然后从小往大,在第一次没取到过的情况下争取放一个就可以大于c
然后记录一下这个情况,加快运算速度
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#define lll long long
using namespace std;
int n,m;
struct co{
int v;
int b;
friend bool operator <(co x,co y){
return x.v<y.v;
}
}c[30];
int sum;
int k;
int v[50];
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
k++;
scanf("%d%d",&c[k].v,&c[k].b);
if(c[k].v>=m) {
sum+=c[k].b;
k--;
continue;
}
}
sort(c+1,c+k+1);
while(1){
int x=m;
// cout<<x<<endl;
for(int i=k;i>=1;--i){
v[i]=0;
// cout<<c[i].b<<endl;
if(c[i].b<=0||c[i].v>x) continue;
// cout<<"DFS"<<endl;
if(c[i].b>=x/c[i].v){
v[i]+=x/c[i].v;
x=x%c[i].v;
}else{
v[i]+=c[i].b;
x-=c[i].b*c[i].v;
}
// cout<<v[i]<<" s";
}
// cout<<x<<endl;
for(int i=1;i<=k;++i){
if(x<=0) break;
if(c[i].b<=v[i]||x>c[i].v) continue;
x-=c[i].v;
v[i]++;
}
if(x>0) break;
int ans=1000000001;
for(int i=1;i<=k;++i){
if(v[i]){
// cout<<i<<" "<<v[i]<<endl;
ans=min(ans,c[i].b/v[i]);
}
}
// cout<<ans<<endl;
for(int i=1;i<=k;++i){
c[i].b-=ans*v[i];
}
sum+=ans;
}
cout<<sum;
return 0;
}