P2376 [USACO09OCT]Allowance G

Lisa

显然的贪心思路就是尽可能的不浪费,

那么就首先从前往后扫,把能拿且不浪费的大的都拿到

然后从小往大,在第一次没取到过的情况下争取放一个就可以大于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;
}
	

原文地址:https://www.cnblogs.com/For-Miku/p/15367619.html