4fd800b3a8 2011-02-23 kinaba: #include <iostream> 4fd800b3a8 2011-02-23 kinaba: #include <sstream> 4fd800b3a8 2011-02-23 kinaba: #include <iomanip> 4fd800b3a8 2011-02-23 kinaba: #include <vector> 4fd800b3a8 2011-02-23 kinaba: #include <string> 4fd800b3a8 2011-02-23 kinaba: #include <map> 4fd800b3a8 2011-02-23 kinaba: #include <set> 4fd800b3a8 2011-02-23 kinaba: #include <algorithm> 4fd800b3a8 2011-02-23 kinaba: #include <numeric> 4fd800b3a8 2011-02-23 kinaba: #include <iterator> 4fd800b3a8 2011-02-23 kinaba: #include <functional> 4fd800b3a8 2011-02-23 kinaba: #include <complex> 4fd800b3a8 2011-02-23 kinaba: #include <queue> 4fd800b3a8 2011-02-23 kinaba: #include <stack> 4fd800b3a8 2011-02-23 kinaba: #include <cmath> 4fd800b3a8 2011-02-23 kinaba: #include <cassert> 4fd800b3a8 2011-02-23 kinaba: #include <cstring> 4fd800b3a8 2011-02-23 kinaba: using namespace std; 4fd800b3a8 2011-02-23 kinaba: typedef long long LL; 4fd800b3a8 2011-02-23 kinaba: typedef complex<double> CMP; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: template<typename T> 4fd800b3a8 2011-02-23 kinaba: class IdGen 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: map<T, int> v2id_; 4fd800b3a8 2011-02-23 kinaba: vector<T> id2v_; 4fd800b3a8 2011-02-23 kinaba: public: 4fd800b3a8 2011-02-23 kinaba: int v2id(const T& v) { 4fd800b3a8 2011-02-23 kinaba: if( !v2id_.count(v) ) { v2id_[v] = size(); id2v_.push_back(v); } 4fd800b3a8 2011-02-23 kinaba: return v2id_[v]; 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: const T& id2v(int i) const { return id2v_[i]; } 4fd800b3a8 2011-02-23 kinaba: int size() const { return id2v_.size(); } 4fd800b3a8 2011-02-23 kinaba: }; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: template<typename Vert, typename Cost, typename Flow, int NV=256> 4fd800b3a8 2011-02-23 kinaba: class MinCostFlow 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: IdGen<Vert> idgen; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: vector<int> G[NV]; 4fd800b3a8 2011-02-23 kinaba: Flow F[NV][NV]; 4fd800b3a8 2011-02-23 kinaba: Cost C[NV][NV]; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: public: 4fd800b3a8 2011-02-23 kinaba: void addEdge( Vert s_, Vert t_, Cost c, Flow f ) 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: int s = idgen.v2id(s_), t = idgen.v2id(t_); 4fd800b3a8 2011-02-23 kinaba: G[s].push_back(t); 4fd800b3a8 2011-02-23 kinaba: G[t].push_back(s); 4fd800b3a8 2011-02-23 kinaba: C[s][t] = c; 4fd800b3a8 2011-02-23 kinaba: C[t][s] = -c; 4fd800b3a8 2011-02-23 kinaba: F[s][t] = f; 4fd800b3a8 2011-02-23 kinaba: F[t][s] = 0; 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: pair<Cost, Flow> calc( Vert s_, Vert t_ ) 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: const int N=idgen.size(), S=idgen.v2id(s_), T=idgen.v2id(t_); 4fd800b3a8 2011-02-23 kinaba: static const Cost COST_INF = 1e+300; // !!EDIT HERE!! 4fd800b3a8 2011-02-23 kinaba: static const Flow FLOW_INF = 0x7fffffff; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: Cost total_cost = 0; 4fd800b3a8 2011-02-23 kinaba: Flow total_flow = 0; 4fd800b3a8 2011-02-23 kinaba: vector<Cost> h(N, 0); // potential 4fd800b3a8 2011-02-23 kinaba: for(Flow RF=FLOW_INF; RF>0; ) // residual flow 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: // Dijkstra -- find the min-cost path 4fd800b3a8 2011-02-23 kinaba: vector<Cost> d(N, COST_INF); d[S] = 0; 4fd800b3a8 2011-02-23 kinaba: vector<int> prev(N, -1); 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: typedef pair< Cost, pair<int,int> > cedge; 4fd800b3a8 2011-02-23 kinaba: priority_queue< cedge, vector<cedge>, greater<cedge> > Q; 4fd800b3a8 2011-02-23 kinaba: Q.push( cedge(0, make_pair(S,S)) ); 4fd800b3a8 2011-02-23 kinaba: while( !Q.empty() ) { 4fd800b3a8 2011-02-23 kinaba: cedge e = Q.top(); Q.pop(); 4fd800b3a8 2011-02-23 kinaba: if( prev[e.second.second] >= 0 ) 4fd800b3a8 2011-02-23 kinaba: continue; 4fd800b3a8 2011-02-23 kinaba: prev[e.second.second] = e.second.first; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: int u = e.second.second; 4fd800b3a8 2011-02-23 kinaba: for(int i=0; i<G[u].size(); ++i) { 4fd800b3a8 2011-02-23 kinaba: int v = G[u][i]; 4fd800b3a8 2011-02-23 kinaba: Cost r_cost = C[u][v] + h[u] - h[v]; 4fd800b3a8 2011-02-23 kinaba: if( F[u][v] > 0 && d[v] > d[u]+r_cost ) 4fd800b3a8 2011-02-23 kinaba: Q.push( cedge(d[v]=d[u]+r_cost, make_pair(u,v)) ); 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: if( prev[T] < 0 ) 4fd800b3a8 2011-02-23 kinaba: break; // Finished 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: // Run the flow as much as possible 4fd800b3a8 2011-02-23 kinaba: Flow f = RF; 4fd800b3a8 2011-02-23 kinaba: for(int u=T; u!=S; u=prev[u]) 4fd800b3a8 2011-02-23 kinaba: f = min(f, F[prev[u]][u]); 4fd800b3a8 2011-02-23 kinaba: RF -= f; 4fd800b3a8 2011-02-23 kinaba: total_flow += f; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: for(int u=T; u!=S; u=prev[u]) 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: total_cost += f * C[prev[u]][u]; 4fd800b3a8 2011-02-23 kinaba: F[prev[u]][u] -= f; 4fd800b3a8 2011-02-23 kinaba: F[u][prev[u]] += f; 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: // Update the potential 4fd800b3a8 2011-02-23 kinaba: for(int u=0; u<N; ++u) 4fd800b3a8 2011-02-23 kinaba: h[u] += d[u]; 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: return make_pair(total_cost, total_flow); 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: }; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: class FoxCardGame { public: 4fd800b3a8 2011-02-23 kinaba: double theMaxProportion(vector <double> pileA, vector <double> pileB, int k) 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: double L=1, R=50; 4fd800b3a8 2011-02-23 kinaba: for(int i=0; i<50; ++i) 4fd800b3a8 2011-02-23 kinaba: (possible(pileA, pileB, k, (L+R)/2) ? L : R) = (L+R)/2; 4fd800b3a8 2011-02-23 kinaba: return L; 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: enum Tag {Src, Left, Right, Target, Goal}; 4fd800b3a8 2011-02-23 kinaba: bool possible(vector <double> pileA, vector <double> pileB, int k, double R) 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: MinCostFlow<pair<Tag,int>, double, int> mcf; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: for(int a=0; a<pileA.size(); ++a) 4fd800b3a8 2011-02-23 kinaba: mcf.addEdge( make_pair(Src,0), make_pair(Left,a), 0.0, 1 ); 4fd800b3a8 2011-02-23 kinaba: for(int a=0; a<pileA.size(); ++a) 4fd800b3a8 2011-02-23 kinaba: for(int b=0; b<pileB.size(); ++b) 4fd800b3a8 2011-02-23 kinaba: { 4fd800b3a8 2011-02-23 kinaba: double x_ = pileA[a]+pileB[b], y_ = pileA[a]*pileB[b]; 4fd800b3a8 2011-02-23 kinaba: double x = max(x_,y_), y = min(x_,y_); 4fd800b3a8 2011-02-23 kinaba: mcf.addEdge( make_pair(Left,a), make_pair(Right,b), R*y-x+10000.0, 1 ); 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: for(int b=0; b<pileB.size(); ++b) 4fd800b3a8 2011-02-23 kinaba: mcf.addEdge( make_pair(Right,b), make_pair(Target,0), 0.0, 1 ); 4fd800b3a8 2011-02-23 kinaba: mcf.addEdge( make_pair(Target,0), make_pair(Goal,0), 0.0, k ); 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: return mcf.calc( make_pair(Src,0), make_pair(Goal,0) ).first <= 10000.0*k; 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: }; 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: // BEGIN CUT HERE 4fd800b3a8 2011-02-23 kinaba: #include <ctime> 4fd800b3a8 2011-02-23 kinaba: double start_time; string timer() 4fd800b3a8 2011-02-23 kinaba: { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } 4fd800b3a8 2011-02-23 kinaba: template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) 4fd800b3a8 2011-02-23 kinaba: { os << "{ "; 4fd800b3a8 2011-02-23 kinaba: for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it) 4fd800b3a8 2011-02-23 kinaba: os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } 4fd800b3a8 2011-02-23 kinaba: void verify_case(const double& Expected, const double& Received) { 4fd800b3a8 2011-02-23 kinaba: bool ok = (abs(Expected - Received) < 1e-9); 4fd800b3a8 2011-02-23 kinaba: if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; 4fd800b3a8 2011-02-23 kinaba: cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } 4fd800b3a8 2011-02-23 kinaba: #define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); 4fd800b3a8 2011-02-23 kinaba: #define END verify_case(_, FoxCardGame().theMaxProportion(pileA, pileB, k));} 4fd800b3a8 2011-02-23 kinaba: int main(){ 4fd800b3a8 2011-02-23 kinaba: 4fd800b3a8 2011-02-23 kinaba: CASE(0) 4fd800b3a8 2011-02-23 kinaba: double pileA_[] = {1, 2, 3}; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileA(pileA_, pileA_+sizeof(pileA_)/sizeof(*pileA_)); 4fd800b3a8 2011-02-23 kinaba: double pileB_[] = {4, 5, 6}; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileB(pileB_, pileB_+sizeof(pileB_)/sizeof(*pileB_)); 4fd800b3a8 2011-02-23 kinaba: int k = 2; 4fd800b3a8 2011-02-23 kinaba: double _ = 1.7692307692309948; 4fd800b3a8 2011-02-23 kinaba: END 4fd800b3a8 2011-02-23 kinaba: CASE(1) 4fd800b3a8 2011-02-23 kinaba: double pileA_[] = {1.234, 5.678, 9.012, 3.456, 7.89}; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileA(pileA_, pileA_+sizeof(pileA_)/sizeof(*pileA_)); 4fd800b3a8 2011-02-23 kinaba: double pileB_[] = {2.345, 6.789, 9.876, 5.432, 1.012}; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileB(pileB_, pileB_+sizeof(pileB_)/sizeof(*pileB_)); 4fd800b3a8 2011-02-23 kinaba: int k = 3; 4fd800b3a8 2011-02-23 kinaba: double _ = 4.159424420079586; 4fd800b3a8 2011-02-23 kinaba: END 4fd800b3a8 2011-02-23 kinaba: CASE(2) 4fd800b3a8 2011-02-23 kinaba: double pileA_[] = {1, 1.1, 1.2, 1.3, 1.4, 1.5}; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileA(pileA_, pileA_+sizeof(pileA_)/sizeof(*pileA_)); 4fd800b3a8 2011-02-23 kinaba: double pileB_[] = {5, 10, 15, 20, 25, 30}; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileB(pileB_, pileB_+sizeof(pileB_)/sizeof(*pileB_)); 4fd800b3a8 2011-02-23 kinaba: int k = 2; 4fd800b3a8 2011-02-23 kinaba: double _ = 1.3972602739726827; 4fd800b3a8 2011-02-23 kinaba: END 4fd800b3a8 2011-02-23 kinaba: CASE(3) 4fd800b3a8 2011-02-23 kinaba: double pileA_[] = {85.302, 92.798, 76.813, 37.994, 36.737, 98.659}; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileA(pileA_, pileA_+sizeof(pileA_)/sizeof(*pileA_)); 4fd800b3a8 2011-02-23 kinaba: double pileB_[] = {13.352, 7.3094, 54.761, 8.2706, 63.223, 37.486}; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileB(pileB_, pileB_+sizeof(pileB_)/sizeof(*pileB_)); 4fd800b3a8 2011-02-23 kinaba: int k = 3; 4fd800b3a8 2011-02-23 kinaba: double _ = 33.58603889836175; 4fd800b3a8 2011-02-23 kinaba: END 4fd800b3a8 2011-02-23 kinaba: CASE(4) 4fd800b3a8 2011-02-23 kinaba: double pileA_[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0}; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileA(pileA_, pileA_+sizeof(pileA_)/sizeof(*pileA_)); 4fd800b3a8 2011-02-23 kinaba: double pileB_[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, 40.0, 41.0, 42.0, 43.0, 44.0, 45.0, 46.0, 47.0, 48.0, 49.0, 50.0}; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileB(pileB_, pileB_+sizeof(pileB_)/sizeof(*pileB_)); 4fd800b3a8 2011-02-23 kinaba: int k = 50; 4fd800b3a8 2011-02-23 kinaba: double _ = 16.846938775510203; 4fd800b3a8 2011-02-23 kinaba: END 4fd800b3a8 2011-02-23 kinaba: /* 4fd800b3a8 2011-02-23 kinaba: CASE(5) 4fd800b3a8 2011-02-23 kinaba: double pileA_[] = ; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileA(pileA_, pileA_+sizeof(pileA_)/sizeof(*pileA_)); 4fd800b3a8 2011-02-23 kinaba: double pileB_[] = ; 4fd800b3a8 2011-02-23 kinaba: vector <double> pileB(pileB_, pileB_+sizeof(pileB_)/sizeof(*pileB_)); 4fd800b3a8 2011-02-23 kinaba: int k = ; 4fd800b3a8 2011-02-23 kinaba: double _ = ; 4fd800b3a8 2011-02-23 kinaba: END 4fd800b3a8 2011-02-23 kinaba: */ 4fd800b3a8 2011-02-23 kinaba: } 4fd800b3a8 2011-02-23 kinaba: // END CUT HERE