DELETED SRM/549-U/1A.cpp Index: SRM/549-U/1A.cpp ================================================================== --- SRM/549-U/1A.cpp +++ SRM/549-U/1A.cpp @@ -1,204 +0,0 @@ -#include <iostream> -#include <sstream> -#include <iomanip> -#include <vector> -#include <string> -#include <map> -#include <set> -#include <algorithm> -#include <numeric> -#include <iterator> -#include <functional> -#include <complex> -#include <queue> -#include <stack> -#include <cmath> -#include <cassert> -using namespace std; -typedef long long LL; -typedef long double LD; -typedef complex<LD> CMP; - -typedef int vert; -typedef vert edge; -typedef vector<edge> edges; -typedef vector<edges> graph; - -bool augment( graph& G, int v, vector<vert>& matchTo, bool visited[] ) -{ - for(int i=0; i<G[v].size(); ++i) { - vert u = G[v][i]; - if( visited[u] ) continue; - visited[u] = true; - - if( matchTo[u]<0 || augment(G, matchTo[u], matchTo, visited) ) - { matchTo[v]=u, matchTo[u]=v; return true; } - } - return false; -} - -template<int NV> -int biMatch( graph& G, int L ) // [0,L):left, [L,?):right -{ - vector<vert> matchTo(G.size(), -1); - int ans = 0; - for(vert v=0; v<L; ++v) { - bool visited[NV] = {}; - if( augment(G, v, matchTo, visited) ) - ++ans; - } - return ans; -} - -class PointyWizardHats { public: - int getNumHats(vector <int> topHeight, vector <int> topRadius, vector <int> bottomHeight, vector <int> bottomRadius) - { - int L = topHeight.size(); - int R = bottomHeight.size(); - graph G(L+R); - for(int i=0; i<L; ++i) - for(int k=0; k<R; ++k) - if( ok(topHeight[i], topRadius[i], bottomHeight[k], bottomRadius[k]) ) - G[i].push_back(L+k); - return biMatch<100>(G, L); - } - - bool ok(int th, int tr, int bh, int br) - { - if( th*br > bh*tr ) { - return br > tr; - } - return false; - } -}; - -// BEGIN CUT HERE -#include <ctime> -double start_time; string timer() - { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } -template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) - { os << "{ "; - for(typename vector<T>::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(_, PointyWizardHats().getNumHats(topHeight, topRadius, bottomHeight, bottomRadius));} -int main(){ - -CASE(0) - int topHeight_[] = {30}; - vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); - int topRadius_[] = {3}; - vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); - int bottomHeight_[] = {3}; - vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); - int bottomRadius_[] = {30}; - vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); - int _ = 1; -END -CASE(1) - int topHeight_[] = {4,4}; - vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); - int topRadius_[] = {4,3}; - vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); - int bottomHeight_[] = {5,12}; - vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); - int bottomRadius_[] = {5,4}; - vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); - int _ = 1; -END -CASE(2) - int topHeight_[] = {3}; - vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); - int topRadius_[] = {3}; - vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); - int bottomHeight_[] = {1,1}; - vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); - int bottomRadius_[] = {2,4}; - vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); - int _ = 1; -END -CASE(3) - int topHeight_[] = {10,10}; - vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); - int topRadius_[] = {2,5}; - vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); - int bottomHeight_[] = {2,9}; - vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); - int bottomRadius_[] = {3,6}; - vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); - int _ = 2; -END -CASE(4) - int topHeight_[] = {3,4,5}; - vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); - int topRadius_[] = {5,4,3}; - vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); - int bottomHeight_[] = {3,4,5}; - vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); - int bottomRadius_[] = {3,8,5}; - vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); - int _ = 2; -END -CASE(5) - int topHeight_[] = {1,2,3,4,5}; - vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); - int topRadius_[] = {2,3,4,5,6}; - vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); - int bottomHeight_[] = {2,3,4,5,6}; - vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); - int bottomRadius_[] = {1,2,3,4,5}; - vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); - int _ = 0; -END -CASE(6) - int topHeight_[] = {123,214,232,323,342,343}; - vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); - int topRadius_[] = {123,123,232,123,323,434}; - vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); - int bottomHeight_[] = {545,322,123,545,777,999}; - vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); - int bottomRadius_[] = {323,443,123,656,767,888}; - vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); - int _ = 5; -END -CASE(7) - int topHeight_[] = {999,999,999,10000,10000,10000}; - vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); - int topRadius_[] = {10000,10000,10000,1,2,3}; - vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); - int bottomHeight_[] = {2324,2323,234,5454,323,232}; - vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); - int bottomRadius_[] = {1,2,3222,434,5454,23}; - vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); - int _ = 3; -END -/* -CASE(8) - int topHeight_[] = ; - vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); - int topRadius_[] = ; - vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); - int bottomHeight_[] = ; - vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); - int bottomRadius_[] = ; - vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); - int _ = ; -END -CASE(9) - int topHeight_[] = ; - vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); - int topRadius_[] = ; - vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); - int bottomHeight_[] = ; - vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); - int bottomRadius_[] = ; - vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); - int _ = ; -END -*/ -} -// END CUT HERE DELETED SRM/549-U/1B.cpp Index: SRM/549-U/1B.cpp ================================================================== --- SRM/549-U/1B.cpp +++ SRM/549-U/1B.cpp @@ -1,265 +0,0 @@ -#include <iostream> -#include <sstream> -#include <iomanip> -#include <vector> -#include <string> -#include <map> -#include <set> -#include <algorithm> -#include <numeric> -#include <iterator> -#include <functional> -#include <complex> -#include <queue> -#include <stack> -#include <cmath> -#include <cassert> -using namespace std; -typedef long long LL; -typedef long double LD; -typedef complex<LD> CMP; - -class MagicalHats { public: - int NC, NH, H, W, NG; - vector<int> gain; - vector< pair<int,int> > hats; - vector<int> tate_base, yoko_base; - - int findMaximumReward(vector <string> board, vector <int> coins, int numGuesses) - { - NC = coins.size(); - sort(coins.begin(), coins.end()); - gain.assign(NC+1, 0); - partial_sum(coins.begin(), coins.end(), gain.begin()+1); - - H = board.size(); - W = board[0].size(); - hats.clear(); - tate_base.resize(W); - yoko_base.resize(H); - for(int y=0; y<H; ++y) - for(int x=0; x<W; ++x) - if(board[y][x] == 'H') { - hats.push_back( make_pair(y,x) ); - tate_base[x]++; - yoko_base[y]++; - } - NH = hats.size(); - NG = numGuesses; - - int m = 0; - for(int i=0; i<NH; ++i) - m = m*3 + 2; - p_memo.resize(m+1); - p_memo_set.resize(m+1); - b_memo.resize(m+1); - b_memo_set.resize(m+1); - return is_possible(m) ? gain[best_num(m, NG)] : -1; - } - - vector<bool> p_memo; - vector<bool> p_memo_set; - bool is_possible(int state) - { - if(p_memo_set[state]) - return p_memo[state]; - p_memo_set[state] = true; - - vector<int> yoko = yoko_base, tate = tate_base, next; - int cnt = 0; - for(int i=0,m=1; i<NH; ++i,m*=3) - { - int v = (state/m)%3; - if( v == 1 ) { - int y = hats[i].first; - int x = hats[i].second; - yoko[y]++; - tate[x]++; - ++cnt; - } else if( v == 2 ) { - next.push_back(m); - } - } - if( next.empty() ) - { - if( cnt != NC ) - return false; - for(int y=0; y<yoko.size(); ++y) - if(yoko[y]%2 != 0) - return p_memo[state] = false; - for(int x=0; x<tate.size(); ++x) - if(tate[x]%2 != 0) - return p_memo[state] = false; - return p_memo[state] = true; - } - else - { - int m = next[0]; - int s[] = {state-2*m, state-m}; - return p_memo[state] = ( is_possible(s[0]) || is_possible(s[1]) ); - } - } - - vector<char> b_memo; - vector<bool> b_memo_set; - char best_num(int state, int guess) - { - if( guess==0 ) - return 0; - if(b_memo_set[state]) - return b_memo[state]; - b_memo_set[state] = true; - - char best = 0; - for(int i=0,m=1; i<NH; ++i,m*=3) - { - int v = (state/m)%3; - if( v == 2 ) - { - int s[] = {state-2*m, state-m}; - char score = 13; - if( is_possible(s[0]) ) - score = min(score, best_num(s[0], guess-1)); - if( is_possible(s[1]) ) - score = min<char>(score, best_num(s[1], guess-1)+1); - best = max(best, score); - } - } - return b_memo[state] = best; - } -}; - -// BEGIN CUT HERE -#include <ctime> -double start_time; string timer() - { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } -template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) - { os << "{ "; - for(typename vector<T>::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(_, MagicalHats().findMaximumReward(board, coins, numGuesses));} -int main(){ - -CASE(0) - string board_[] = {"H"}; - vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); - int coins_[] = {1}; - vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); - int numGuesses = 1; - int _ = 1; -END -CASE(1) - string board_[] = {"HHH", - "H.H", - "HH."}; - vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); - int coins_[] = {9}; - vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); - int numGuesses = 1; - int _ = 9; -END -CASE(2) - string board_[] = {"HH", - "HH"}; - vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); - int coins_[] = {1,2,3,4}; - vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); - int numGuesses = 3; - int _ = 6; -END -CASE(3) - string board_[] = {"HHH", - "HHH", - "H.H"}; - vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); - int coins_[] = {13,13,13,13}; - vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); - int numGuesses = 2; - int _ = 13; -END -CASE(4) - string board_[] = {"HHH", - "HHH", - "H.H"}; - vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); - int coins_[] = {13,13,13,13}; - vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); - int numGuesses = 3; - int _ = 26; -END -CASE(5) - string board_[] = {"H.H.", - ".H.H", - "H.H."}; - vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); - int coins_[] = {17}; - vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); - int numGuesses = 6; - int _ = -1; -END -CASE(6) - string board_[] = {"HHH..........", - "H.H..........", - "HHH..........", - "H.H..........", - "HHH.........." -".............", -".............", -".............", -".............", -".............", -".............", -".............", -".............", -}; - vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); - int coins_[] = {33,337,1007,2403,5601,6003,9999}; - vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); - int numGuesses = 5; - int _ = 1377; -END -CASE(7) - string board_[] = {".............", - ".............", - ".............", - ".............", - ".............", - ".............", - ".....H.H.....", - "......H......", - ".....H.H.....", - ".............", - ".............", - ".............", - "............."}; - vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); - int coins_[] = {22}; - vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); - int numGuesses = 3; - int _ = 22; -END -/* -CASE(8) - string board_[] = ; - vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); - int coins_[] = ; - vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); - int numGuesses = ; - int _ = ; -END -CASE(9) - string board_[] = ; - vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); - int coins_[] = ; - vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); - int numGuesses = ; - int _ = ; -END -*/ -} -// END CUT HERE ADDED SRM/549/1A.cpp Index: SRM/549/1A.cpp ================================================================== --- SRM/549/1A.cpp +++ SRM/549/1A.cpp @@ -0,0 +1,204 @@ +#include <iostream> +#include <sstream> +#include <iomanip> +#include <vector> +#include <string> +#include <map> +#include <set> +#include <algorithm> +#include <numeric> +#include <iterator> +#include <functional> +#include <complex> +#include <queue> +#include <stack> +#include <cmath> +#include <cassert> +using namespace std; +typedef long long LL; +typedef long double LD; +typedef complex<LD> CMP; + +typedef int vert; +typedef vert edge; +typedef vector<edge> edges; +typedef vector<edges> graph; + +bool augment( graph& G, int v, vector<vert>& matchTo, bool visited[] ) +{ + for(int i=0; i<G[v].size(); ++i) { + vert u = G[v][i]; + if( visited[u] ) continue; + visited[u] = true; + + if( matchTo[u]<0 || augment(G, matchTo[u], matchTo, visited) ) + { matchTo[v]=u, matchTo[u]=v; return true; } + } + return false; +} + +template<int NV> +int biMatch( graph& G, int L ) // [0,L):left, [L,?):right +{ + vector<vert> matchTo(G.size(), -1); + int ans = 0; + for(vert v=0; v<L; ++v) { + bool visited[NV] = {}; + if( augment(G, v, matchTo, visited) ) + ++ans; + } + return ans; +} + +class PointyWizardHats { public: + int getNumHats(vector <int> topHeight, vector <int> topRadius, vector <int> bottomHeight, vector <int> bottomRadius) + { + int L = topHeight.size(); + int R = bottomHeight.size(); + graph G(L+R); + for(int i=0; i<L; ++i) + for(int k=0; k<R; ++k) + if( ok(topHeight[i], topRadius[i], bottomHeight[k], bottomRadius[k]) ) + G[i].push_back(L+k); + return biMatch<100>(G, L); + } + + bool ok(int th, int tr, int bh, int br) + { + if( th*br > bh*tr ) { + return br > tr; + } + return false; + } +}; + +// BEGIN CUT HERE +#include <ctime> +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) + { os << "{ "; + for(typename vector<T>::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(_, PointyWizardHats().getNumHats(topHeight, topRadius, bottomHeight, bottomRadius));} +int main(){ + +CASE(0) + int topHeight_[] = {30}; + vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); + int topRadius_[] = {3}; + vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); + int bottomHeight_[] = {3}; + vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); + int bottomRadius_[] = {30}; + vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); + int _ = 1; +END +CASE(1) + int topHeight_[] = {4,4}; + vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); + int topRadius_[] = {4,3}; + vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); + int bottomHeight_[] = {5,12}; + vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); + int bottomRadius_[] = {5,4}; + vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); + int _ = 1; +END +CASE(2) + int topHeight_[] = {3}; + vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); + int topRadius_[] = {3}; + vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); + int bottomHeight_[] = {1,1}; + vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); + int bottomRadius_[] = {2,4}; + vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); + int _ = 1; +END +CASE(3) + int topHeight_[] = {10,10}; + vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); + int topRadius_[] = {2,5}; + vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); + int bottomHeight_[] = {2,9}; + vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); + int bottomRadius_[] = {3,6}; + vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); + int _ = 2; +END +CASE(4) + int topHeight_[] = {3,4,5}; + vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); + int topRadius_[] = {5,4,3}; + vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); + int bottomHeight_[] = {3,4,5}; + vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); + int bottomRadius_[] = {3,8,5}; + vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); + int _ = 2; +END +CASE(5) + int topHeight_[] = {1,2,3,4,5}; + vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); + int topRadius_[] = {2,3,4,5,6}; + vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); + int bottomHeight_[] = {2,3,4,5,6}; + vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); + int bottomRadius_[] = {1,2,3,4,5}; + vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); + int _ = 0; +END +CASE(6) + int topHeight_[] = {123,214,232,323,342,343}; + vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); + int topRadius_[] = {123,123,232,123,323,434}; + vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); + int bottomHeight_[] = {545,322,123,545,777,999}; + vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); + int bottomRadius_[] = {323,443,123,656,767,888}; + vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); + int _ = 5; +END +CASE(7) + int topHeight_[] = {999,999,999,10000,10000,10000}; + vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); + int topRadius_[] = {10000,10000,10000,1,2,3}; + vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); + int bottomHeight_[] = {2324,2323,234,5454,323,232}; + vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); + int bottomRadius_[] = {1,2,3222,434,5454,23}; + vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); + int _ = 3; +END +/* +CASE(8) + int topHeight_[] = ; + vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); + int topRadius_[] = ; + vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); + int bottomHeight_[] = ; + vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); + int bottomRadius_[] = ; + vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); + int _ = ; +END +CASE(9) + int topHeight_[] = ; + vector <int> topHeight(topHeight_, topHeight_+sizeof(topHeight_)/sizeof(*topHeight_)); + int topRadius_[] = ; + vector <int> topRadius(topRadius_, topRadius_+sizeof(topRadius_)/sizeof(*topRadius_)); + int bottomHeight_[] = ; + vector <int> bottomHeight(bottomHeight_, bottomHeight_+sizeof(bottomHeight_)/sizeof(*bottomHeight_)); + int bottomRadius_[] = ; + vector <int> bottomRadius(bottomRadius_, bottomRadius_+sizeof(bottomRadius_)/sizeof(*bottomRadius_)); + int _ = ; +END +*/ +} +// END CUT HERE ADDED SRM/549/1B.cpp Index: SRM/549/1B.cpp ================================================================== --- SRM/549/1B.cpp +++ SRM/549/1B.cpp @@ -0,0 +1,265 @@ +#include <iostream> +#include <sstream> +#include <iomanip> +#include <vector> +#include <string> +#include <map> +#include <set> +#include <algorithm> +#include <numeric> +#include <iterator> +#include <functional> +#include <complex> +#include <queue> +#include <stack> +#include <cmath> +#include <cassert> +using namespace std; +typedef long long LL; +typedef long double LD; +typedef complex<LD> CMP; + +class MagicalHats { public: + int NC, NH, H, W, NG; + vector<int> gain; + vector< pair<int,int> > hats; + vector<int> tate_base, yoko_base; + + int findMaximumReward(vector <string> board, vector <int> coins, int numGuesses) + { + NC = coins.size(); + sort(coins.begin(), coins.end()); + gain.assign(NC+1, 0); + partial_sum(coins.begin(), coins.end(), gain.begin()+1); + + H = board.size(); + W = board[0].size(); + hats.clear(); + tate_base.resize(W); + yoko_base.resize(H); + for(int y=0; y<H; ++y) + for(int x=0; x<W; ++x) + if(board[y][x] == 'H') { + hats.push_back( make_pair(y,x) ); + tate_base[x]++; + yoko_base[y]++; + } + NH = hats.size(); + NG = numGuesses; + + int m = 0; + for(int i=0; i<NH; ++i) + m = m*3 + 2; + p_memo.resize(m+1); + p_memo_set.resize(m+1); + b_memo.resize(m+1); + b_memo_set.resize(m+1); + return is_possible(m) ? gain[best_num(m, NG)] : -1; + } + + vector<bool> p_memo; + vector<bool> p_memo_set; + bool is_possible(int state) + { + if(p_memo_set[state]) + return p_memo[state]; + p_memo_set[state] = true; + + vector<int> yoko = yoko_base, tate = tate_base, next; + int cnt = 0; + for(int i=0,m=1; i<NH; ++i,m*=3) + { + int v = (state/m)%3; + if( v == 1 ) { + int y = hats[i].first; + int x = hats[i].second; + yoko[y]++; + tate[x]++; + ++cnt; + } else if( v == 2 ) { + next.push_back(m); + } + } + if( next.empty() ) + { + if( cnt != NC ) + return false; + for(int y=0; y<yoko.size(); ++y) + if(yoko[y]%2 != 0) + return p_memo[state] = false; + for(int x=0; x<tate.size(); ++x) + if(tate[x]%2 != 0) + return p_memo[state] = false; + return p_memo[state] = true; + } + else + { + int m = next[0]; + int s[] = {state-2*m, state-m}; + return p_memo[state] = ( is_possible(s[0]) || is_possible(s[1]) ); + } + } + + vector<char> b_memo; + vector<bool> b_memo_set; + char best_num(int state, int guess) + { + if( guess==0 ) + return 0; + if(b_memo_set[state]) + return b_memo[state]; + b_memo_set[state] = true; + + char best = 0; + for(int i=0,m=1; i<NH; ++i,m*=3) + { + int v = (state/m)%3; + if( v == 2 ) + { + int s[] = {state-2*m, state-m}; + char score = 13; + if( is_possible(s[0]) ) + score = min(score, best_num(s[0], guess-1)); + if( is_possible(s[1]) ) + score = min<char>(score, best_num(s[1], guess-1)+1); + best = max(best, score); + } + } + return b_memo[state] = best; + } +}; + +// BEGIN CUT HERE +#include <ctime> +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) + { os << "{ "; + for(typename vector<T>::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(_, MagicalHats().findMaximumReward(board, coins, numGuesses));} +int main(){ + +CASE(0) + string board_[] = {"H"}; + vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); + int coins_[] = {1}; + vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); + int numGuesses = 1; + int _ = 1; +END +CASE(1) + string board_[] = {"HHH", + "H.H", + "HH."}; + vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); + int coins_[] = {9}; + vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); + int numGuesses = 1; + int _ = 9; +END +CASE(2) + string board_[] = {"HH", + "HH"}; + vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); + int coins_[] = {1,2,3,4}; + vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); + int numGuesses = 3; + int _ = 6; +END +CASE(3) + string board_[] = {"HHH", + "HHH", + "H.H"}; + vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); + int coins_[] = {13,13,13,13}; + vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); + int numGuesses = 2; + int _ = 13; +END +CASE(4) + string board_[] = {"HHH", + "HHH", + "H.H"}; + vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); + int coins_[] = {13,13,13,13}; + vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); + int numGuesses = 3; + int _ = 26; +END +CASE(5) + string board_[] = {"H.H.", + ".H.H", + "H.H."}; + vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); + int coins_[] = {17}; + vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); + int numGuesses = 6; + int _ = -1; +END +CASE(6) + string board_[] = {"HHH..........", + "H.H..........", + "HHH..........", + "H.H..........", + "HHH.........." +".............", +".............", +".............", +".............", +".............", +".............", +".............", +".............", +}; + vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); + int coins_[] = {33,337,1007,2403,5601,6003,9999}; + vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); + int numGuesses = 5; + int _ = 1377; +END +CASE(7) + string board_[] = {".............", + ".............", + ".............", + ".............", + ".............", + ".............", + ".....H.H.....", + "......H......", + ".....H.H.....", + ".............", + ".............", + ".............", + "............."}; + vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); + int coins_[] = {22}; + vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); + int numGuesses = 3; + int _ = 22; +END +/* +CASE(8) + string board_[] = ; + vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); + int coins_[] = ; + vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); + int numGuesses = ; + int _ = ; +END +CASE(9) + string board_[] = ; + vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); + int coins_[] = ; + vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); + int numGuesses = ; + int _ = ; +END +*/ +} +// END CUT HERE ADDED SRM/549/1C.cpp Index: SRM/549/1C.cpp ================================================================== --- SRM/549/1C.cpp +++ SRM/549/1C.cpp @@ -0,0 +1,317 @@ +#include <iostream> +#include <sstream> +#include <iomanip> +#include <vector> +#include <string> +#include <map> +#include <set> +#include <algorithm> +#include <numeric> +#include <iterator> +#include <functional> +#include <complex> +#include <queue> +#include <stack> +#include <cmath> +#include <cassert> +using namespace std; +typedef long long LL; +typedef long double LD; +typedef complex<LD> CMP; + +template<typename Vert, typename Flow, int NV=16> +class MaxFlow +{ + vector<int> 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<int> Q(1, S); + for(int lv=1; !Q.empty(); ++lv) { + vector<int> Q2; + for(size_t i=0; i!=Q.size(); ++i) { + const vector<int>& 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 CosmicBlocks { public: + vector<int> blockTypes; + int N, minWays, maxWays; + + int getNumOrders(vector <int> blockTypes_, int minWays_, int maxWays_) + { + N = blockTypes_.size(); + blockTypes = blockTypes_; + minWays = minWays_; + maxWays = maxWays_; + return try_all_latitude(); + } + + int try_all_latitude() + { + vector<int> lat; + return rec_assign_latitude(&lat, (1<<N)-1, 0x7fffffff); + } + + int rec_assign_latitude(vector<int>* lat, int mask, int prev_lat_blocks) + { + if( mask == 0 ) + return try_all_touching_releation(*lat); + + int total = 0; + for(int m=1; m<=mask; ++m) if( (m&mask)==m ) { + int sum = 0; + for(int i=0; (1<<i)<=m; ++i) if(1<<i & m) + sum+=blockTypes[i]; + if( prev_lat_blocks >= sum ) { + lat->push_back(m); + total += rec_assign_latitude(lat, mask&~m, sum); + lat->pop_back(); + } + } + return total; + } + + int try_all_touching_releation(const vector<int>& lat) + { + int total = 0; + + vector<int> fst = elements(lat[0]); + vector< pair<int,int> > adj = adjacent_blocks(lat); + for(int m=0; m<(1<<adj.size()); ++m) + { + vector< vector<int> > up(N); + up.push_back(fst); + for(int i=0; (1<<i)<=m; ++i) if(1<<i & m) + up[adj[i].first].push_back(adj[i].second); + + if( !possible(up) ) + continue; + int ways = calc_ways(up); + if( minWays<=ways && ways<=maxWays ) + ++total; + } + return total; + } + + vector<int> elements(int mask) + { + vector<int> result; + for(int i=0; (1<<i)<=mask; ++i) if(1<<i & mask) + result.push_back(i); + return result; + } + + vector< pair<int,int> > adjacent_blocks(const vector<int>& lat) + { + vector< pair<int,int> > result; + for(int i=1; i<lat.size(); ++i) + for(int a=0; (1<<a)<=lat[i-1]; ++a) if(1<<a & lat[i-1]) + for(int b=0; (1<<b)<=lat[i]; ++b) if(1<<b & lat[i]) + result.push_back(make_pair(a,b)); + return result; + } + + int calc_ways(const vector< vector<int> >& up) + { + vector<int> governed(N); + for(int i=0; i<up.size(); ++i) + for(int k=0; k<up[i].size(); ++k) + governed[up[i][k]] ++; + + // trivial check 2 + for(int i=0; i<governed.size(); ++i) + if(governed[i] == 0) + return 0; + + vector<int> memo(1<<N, -1); + return calc_ways_rec(N, (1<<N)-1, up, governed, memo); + } + + int calc_ways_rec(int i, int mask, const vector< vector<int> >& up, vector<int>& governed, + vector<int>& memo) + { + if(mask == 0) + return 1; + if(memo[mask] != -1) + return memo[mask]; + + int sum = 0; + + for(int k=0; k<up[i].size(); ++k) governed[up[i][k]]--; + { + for(int k=0; k<governed.size(); ++k) + if(!governed[k] && (mask & 1<<k)) + sum += calc_ways_rec(k, mask &~ (1<<k), up, governed, memo); + } + for(int k=0; k<up[i].size(); ++k) governed[up[i][k]]++; + + return memo[mask] = sum; + } + + bool possible(const vector< vector<int> >& up) + { + static const int INF = 0x3fffffff; + + int total = accumulate(blockTypes.begin(), blockTypes.end(), 0); + + MaxFlow<int, int> mf; + vector<int> out = blockTypes, in = blockTypes; + for(int v=0; v<=N; ++v) { + for(int i=0; i<up[v].size(); ++i) { + int u = up[v][i]; + mf.addEdge(v, N+1+u, INF); + if(v<N) {in[v] -= 1; if(in[v]<0) return false; } + out[u] -= 1; if(out[u]<0) return false; + total -= 1; + } + } + for(int v=0; v<=N; ++v) + if(v == N) { + mf.addEdge(N+1+N, v, INF); + } else { + mf.addEdge(N+1+N, v, in[v]); + mf.addEdge(N+1+v, N+1+N+1, out[v]); + } + return mf.calc(N+1+N, N+1+N+1) == total; + } +}; + +// BEGIN CUT HERE +#include <ctime> +double start_time; string timer() + { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } +template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) + { os << "{ "; + for(typename vector<T>::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(_, CosmicBlocks().getNumOrders(blockTypes, minWays, maxWays));} +int main(){ + +CASE(0) + int blockTypes_[] = {2,2,2}; + vector <int> blockTypes(blockTypes_, blockTypes_+sizeof(blockTypes_)/sizeof(*blockTypes_)); + int minWays = 1; + int maxWays = 1; + int _ = 6; +END +CASE(1) + int blockTypes_[] = {1,1,1,1,1,1}; + vector <int> blockTypes(blockTypes_, blockTypes_+sizeof(blockTypes_)/sizeof(*blockTypes_)); + int minWays = 720; + int maxWays = 720; + int _ = 1; +END +CASE(2) + int blockTypes_[] = {2,2}; + vector <int> blockTypes(blockTypes_, blockTypes_+sizeof(blockTypes_)/sizeof(*blockTypes_)); + int minWays = 1; + int maxWays = 2; + int _ = 3; +END +CASE(3) + int blockTypes_[] = {1,2}; + vector <int> blockTypes(blockTypes_, blockTypes_+sizeof(blockTypes_)/sizeof(*blockTypes_)); + int minWays = 1; + int maxWays = 2; + int _ = 2; +END +CASE(4) + int blockTypes_[] = {1}; + vector <int> blockTypes(blockTypes_, blockTypes_+sizeof(blockTypes_)/sizeof(*blockTypes_)); + int minWays = 1; + int maxWays = 1; + int _ = 1; +END +CASE(5) + int blockTypes_[] = {1,2,4,8}; + vector <int> blockTypes(blockTypes_, blockTypes_+sizeof(blockTypes_)/sizeof(*blockTypes_)); + int minWays = 5; + int maxWays = 30; + int _ = 27; +END +CASE(6) + int blockTypes_[] = {1,2,3,4,5,6}; + vector <int> blockTypes(blockTypes_, blockTypes_+sizeof(blockTypes_)/sizeof(*blockTypes_)); + int minWays = 1; + int maxWays = 720; + int _ = 4445; +END +CASE(7) + int blockTypes_[] = {7500,1000,7500,1000,7500}; + vector <int> blockTypes(blockTypes_, blockTypes_+sizeof(blockTypes_)/sizeof(*blockTypes_)); + int minWays = 8; + int maxWays = 88; + int _ = 448; +END +/* +CASE(8) + int blockTypes_[] = ; + vector <int> blockTypes(blockTypes_, blockTypes_+sizeof(blockTypes_)/sizeof(*blockTypes_)); + int minWays = ; + int maxWays = ; + int _ = ; +END +CASE(9) + int blockTypes_[] = ; + vector <int> blockTypes(blockTypes_, blockTypes_+sizeof(blockTypes_)/sizeof(*blockTypes_)); + int minWays = ; + int maxWays = ; + int _ = ; +END +*/ +} +// END CUT HERE