TopCoder SRM 355 Div1 Easy MixingLiquids

問題

一種類の物質を溶かした溶液がn種類ある。
それぞれの溶液の濃度はpercent[i]%で、質量はamount[i]グラムである。


溶液を自由に混ぜて、濃度need%の溶液を出来るだけ多く作りたい。
need%の溶液な何グラム出来るか、求めよ。

制約条件

n≦50
0≦percent[i],need≦100
amount[i]≦1000

方針

目的の溶液が最大量得られているとき、
目的の溶液より濃い溶液と、薄い溶液が同時に余っていることはない。
(両方余っていたら、もっと多くの目的の溶液が作れるため)


したがって、薄い溶液を全部使ってから、
濃い溶液を薄い順に入れていくやり方と、
濃い溶液を全部使ってから、薄い溶液を濃い順に入れていくやり方を両方試せば十分。

ソースコード

double solve(vector<pi> a,vector<pi> b,double x,double y,int need){
	rep(i,a.size()){
		x+=a[i].second;
		y+=a[i].second*a[i].first/100.0;
	}
	if(x==0||abs(y/x*100-need)<EPS)return x;
	
	bool sml=y/x*100<need;
	rep(i,b.size()){
		double nx=x+b[i].second, ny=y+b[i].first*b[i].second/100.0;
		
		if(sml&&ny/nx*100+EPS<need||!sml&&ny/nx*100>need+EPS)x=nx, y=ny;
		else{
			double t=(y*100.0-x*need)/(need-b[i].first);
			x+=t;
			return x;
		}
	}
	return INF;
}

class MixingLiquids {
	public:
	double howMuch(vector <int> percent, vector <int> amount, int need) 
	{
		double x=0,y=0;
		vector<pi> a,b;
		int n=percent.size();
		rep(i,n){
			if(percent[i]==need){
				x+=amount[i];
				y+=amount[i]*need/100.0;
			}
			else if(percent[i]<need)a.pb(mp(percent[i],amount[i]));
			else b.pb(mp(percent[i],amount[i]));
		}
		sort(all(a),greater<pi>());
		sort(all(b));
		
		double ans=solve(a,b,x,y,need);
		if(ans==INF)ans=solve(b,a,x,y,need);
		return ans==INF?0.0:ans;
	}
};