ADDED SRM/625-U/1A.cpp Index: SRM/625-U/1A.cpp ================================================================== --- SRM/625-U/1A.cpp +++ SRM/625-U/1A.cpp @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; +typedef long long LL; +typedef complex CMP; + +class PalindromePermutations { public: + double palindromeProbability(string word) + { + map cnt; + for(char c: word) cnt[c]++; + + vector ns; + for(auto cn: cnt) ns.emplace_back(cn.second); + + return solve(ns); + } + + double solve(vector c) + { + if(count_if(c.begin(), c.end(), [&](int x){return x%2==1;}) >= 2) + return 0.0; + return rec(c); + } + + double rec(vector c) + { + if(c.size() <= 1) + return 1.0; + + int n = accumulate(c.begin(), c.end(), 0); + int n2 = n/2; + int k = c.back(); + int k2 = k/2; + c.pop_back(); + return C(n2,k2) / C(n,k) * rec(c); + } + + double C(int n, int k) + { + double v = 1.0; + for(int i=1; i<=k; ++i) + v = v * (n+1-i) / i; + return v; + } +}; + +// BEGIN CUT HERE +#include +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template ostream& operator<<(ostream& os, const vector& v) + { os << "{ "; + for(typename vector::const_iterator it=v.begin(); it!=v.end(); ++it) + os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } +void verify_case(const double& Expected, const double& Received) { + bool ok = (abs(Expected - Received) < 1e-9); + if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; + cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } +#define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); +#define END verify_case(_, PalindromePermutations().palindromeProbability(word));} +int main(){ + +CASE(0) + string word = "haha"; + double _ = 0.3333333333333333; +END +CASE(1) + string word = "xxxxy"; + double _ = 0.2; +END +CASE(2) + string word = "xxxx"; + double _ = 1.0; +END +CASE(3) + string word = "abcde"; + double _ = 0.0; +END +CASE(4) + string word = "hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhff"; + double _ = 0.025641025641025637; +END +/* +CASE(5) + string word = ; + double _ = ; +END +CASE(6) + string word = ; + double _ = ; +END +*/ +} +// END CUT HERE ADDED SRM/625-U/1B.cpp Index: SRM/625-U/1B.cpp ================================================================== --- SRM/625-U/1B.cpp +++ SRM/625-U/1B.cpp @@ -0,0 +1,260 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; +typedef long long LL; +typedef complex CMP; + +template +class MaxFlow +{ + vector G[NV]; + Flow F[NV][NV]; + +public: + void addEdge( Vert s, Vert t, Flow f ) + { + G[s].push_back(t); + G[t].push_back(s); + F[s][t] = f; + F[t][s] = 0; + } + + Flow calc( Vert S, Vert D ) + { + for( Flow total=0 ;; ) { + // Do BFS and compute the level for each node. + int LV[NV] = {0}; + vector Q(1, S); + for(int lv=1; !Q.empty(); ++lv) { + vector Q2; + for(size_t i=0; i!=Q.size(); ++i) { + const vector& ne = G[Q[i]]; + for(size_t j=0; j!=ne.size(); ++j) + if( F[Q[i]][ne[j]] && !LV[ne[j]] && ne[j]!=S ) + LV[ne[j]]=lv, Q2.push_back(ne[j]); + } + Q.swap(Q2); + } + + // Destination is now unreachable. Done. + if( !LV[D] ) + return total; + + // Iterating DFS. + bool blocked[NV] = {}; + total += dinic_dfs( S, D, LV, 0x7fffffff, blocked ); + } + } + +private: + Flow dinic_dfs( int v, int D, int LV[], Flow flow_in, bool blocked[] ) + { + Flow flow_out = 0; + for(size_t i=0; i!=G[v].size(); ++i) { + int u = G[v][i]; + if( LV[v]+1==LV[u] && F[v][u] ) { + Flow f = min(flow_in-flow_out, F[v][u]); + if( u==D || !blocked[u] && (f=dinic_dfs(u,D,LV,f,blocked))>0 ) { + F[v][u] -= f; + F[u][v] += f; + flow_out += f; + if( flow_in == flow_out ) return flow_out; + } + } + } + blocked[v] = (flow_out==0); + return flow_out; + } +}; + +class BlockTheBlockPuzzle { public: + int minimumHoles(vector board) + { + const int H = board.size(); + const int W = board[0].size(); + const int INF = 2500; + for(int gy=0; gy, int> id; + for(int y=gy%3; y* mf = new MaxFlow<>; + enum {IN, OUT}; + + int Goal; + vector Start; + for(int y=gy%3; yaddEdge(v1*2+IN, v1*2+OUT, e); + //cerr << v1 << " -- " << e << " -- " << v1 << endl; + + const int dy[] = {+1,0}; + const int dx[] = {0,+1}; + for(int d=0; d<2; ++d) + { + int Y = y+dy[d]*3; + int X = x+dx[d]*3; + if(0<=Y&&YaddEdge(v1*2+OUT, v2*2+IN, e); + mf->addEdge(v2*2+OUT, v1*2+IN, e); + //cerr << v1 << " -- " << e << " -- " << v2 << endl; + } + } + } + } + + for(int v: Start) { + //cerr << "S: " << v << endl; + mf->addEdge(v*2+OUT, N*2+IN, INF); + } + //cerr << "G: " << Goal << endl; + int ans = mf->calc(Goal*2+OUT, N*2+IN); + delete mf; + return ans>=INF ? -1 : ans; + } + return -1; + } +}; + +// BEGIN CUT HERE +#include +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template ostream& operator<<(ostream& os, const vector& v) + { os << "{ "; + for(typename vector::const_iterator it=v.begin(); it!=v.end(); ++it) + os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } +void verify_case(const int& Expected, const int& Received) { + bool ok = (Expected == Received); + if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; + cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } +#define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); +#define END verify_case(_, BlockTheBlockPuzzle().minimumHoles(board));} +int main(){ + +CASE(0) + string board_[] = {"b..$", + "....", + "HHHH", + "HHHH"}; + vector board(board_, board_+sizeof(board_)/sizeof(*board_)); + int _ = 2; +END +CASE(1) + string board_[] = {"............H..", + "...............", + "...............", + "HHH$HHH.....H..", + "HHHHHHH........", + "HHHHHHHH.......", + "......b..H.....", + "...............", + "...............", + "...H..H..H.....", + "...............", + "...............", + "...............", + "...............", + "..............."}; + vector board(board_, board_+sizeof(board_)/sizeof(*board_)); + int _ = 0; +END +CASE(2) + string board_[] = {"............H..", + "...............", + "...............", + "HHH$HHH........", + "HHHHHHH........", + "HHHHHHHH.......", + "......b..H.....", + "...............", + "...............", + "...H..H..H.....", + "...............", + "...............", + "...............", + "...............", + "..............."}; + vector board(board_, board_+sizeof(board_)/sizeof(*board_)); + int _ = 1; +END +CASE(3) + string board_[] = {"b..$...", + "...H...", + ".......", + "b..b..b", + "...H...", + ".......", + "b..b..b"} + +; + vector board(board_, board_+sizeof(board_)/sizeof(*board_)); + int _ = 4; +END +CASE(4) + string board_[] = {"b..b..b", + "..b..b.", + ".......", + "b..$bbb", + ".b.....", + "....b..", + "b..b..b"} +; + vector board(board_, board_+sizeof(board_)/sizeof(*board_)); + int _ = -1; +END +/* +CASE(5) + string board_[] = ; + vector board(board_, board_+sizeof(board_)/sizeof(*board_)); + int _ = ; +END +CASE(6) + string board_[] = ; + vector board(board_, board_+sizeof(board_)/sizeof(*board_)); + int _ = ; +END +*/ +} +// END CUT HERE