OUPC2012 問題E Fractional Knapsack (AOJ2354)
制約条件
n≦10^5
w≦10^5
-10^4≦wi≦10^4
-10^4≦vi≦10^4
方針
v≧0,w≦0の品物は無条件に全て使う。
v≦0,w≧0の品物は無条件に全て捨てる。
残り、v≦0,w≦0の品物は、使ったことにして、(-v,-w)の、符号が逆の品物があることにする。
すると全ての品物がv≧0,w≧0の場合に帰着されるので、
v/wが大きい順に貪欲に使っていけばよい。
ソースコード
bool cmp(const pi &a,const pi &b){ return a.second*b.first>a.first*b.second; } int n; double W; vector<pi> p; int main(){ cin>>n>>W; double ans=0; rep(i,n){ int w,v; cin>>w>>v; if(w<=0&&v>=0)ans+=v, W-=w; else if(v<=0&&w>=0)continue; else if(v>0&&w>0)p.pb(mp(w,v)); else{ p.pb(mp(-w,-v)); ans+=v, W-=w; } } sort(all(p),cmp); for(int i=0;i<p.size();i++){ double use=min(1.0,W/p[i].first); W-=use*p[i].first; ans+=p[i].second*use; if(W<EPS)break; } printf("%.12f\n",ans); return 0; }