c9008fc667 2012-08-08 kinaba: #include <iostream> c9008fc667 2012-08-08 kinaba: #include <sstream> c9008fc667 2012-08-08 kinaba: #include <iomanip> c9008fc667 2012-08-08 kinaba: #include <vector> c9008fc667 2012-08-08 kinaba: #include <string> c9008fc667 2012-08-08 kinaba: #include <map> c9008fc667 2012-08-08 kinaba: #include <set> c9008fc667 2012-08-08 kinaba: #include <algorithm> c9008fc667 2012-08-08 kinaba: #include <numeric> c9008fc667 2012-08-08 kinaba: #include <iterator> c9008fc667 2012-08-08 kinaba: #include <functional> c9008fc667 2012-08-08 kinaba: #include <complex> c9008fc667 2012-08-08 kinaba: #include <queue> c9008fc667 2012-08-08 kinaba: #include <stack> c9008fc667 2012-08-08 kinaba: #include <cmath> c9008fc667 2012-08-08 kinaba: #include <cassert> c9008fc667 2012-08-08 kinaba: using namespace std; c9008fc667 2012-08-08 kinaba: typedef long long LL; c9008fc667 2012-08-08 kinaba: typedef long double LD; c9008fc667 2012-08-08 kinaba: typedef complex<LD> CMP; c9008fc667 2012-08-08 kinaba: c9008fc667 2012-08-08 kinaba: class MagicalHats { public: c9008fc667 2012-08-08 kinaba: int NC, NH, H, W, NG; c9008fc667 2012-08-08 kinaba: vector<int> gain; c9008fc667 2012-08-08 kinaba: vector< pair<int,int> > hats; c9008fc667 2012-08-08 kinaba: vector<int> tate_base, yoko_base; c9008fc667 2012-08-08 kinaba: c9008fc667 2012-08-08 kinaba: int findMaximumReward(vector <string> board, vector <int> coins, int numGuesses) c9008fc667 2012-08-08 kinaba: { c9008fc667 2012-08-08 kinaba: NC = coins.size(); c9008fc667 2012-08-08 kinaba: sort(coins.begin(), coins.end()); c9008fc667 2012-08-08 kinaba: gain.assign(NC+1, 0); c9008fc667 2012-08-08 kinaba: partial_sum(coins.begin(), coins.end(), gain.begin()+1); c9008fc667 2012-08-08 kinaba: c9008fc667 2012-08-08 kinaba: H = board.size(); c9008fc667 2012-08-08 kinaba: W = board[0].size(); c9008fc667 2012-08-08 kinaba: hats.clear(); c9008fc667 2012-08-08 kinaba: tate_base.resize(W); c9008fc667 2012-08-08 kinaba: yoko_base.resize(H); c9008fc667 2012-08-08 kinaba: for(int y=0; y<H; ++y) c9008fc667 2012-08-08 kinaba: for(int x=0; x<W; ++x) c9008fc667 2012-08-08 kinaba: if(board[y][x] == 'H') { c9008fc667 2012-08-08 kinaba: hats.push_back( make_pair(y,x) ); c9008fc667 2012-08-08 kinaba: tate_base[x]++; c9008fc667 2012-08-08 kinaba: yoko_base[y]++; c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: NH = hats.size(); c9008fc667 2012-08-08 kinaba: NG = numGuesses; c9008fc667 2012-08-08 kinaba: c9008fc667 2012-08-08 kinaba: int m = 0; c9008fc667 2012-08-08 kinaba: for(int i=0; i<NH; ++i) c9008fc667 2012-08-08 kinaba: m = m*3 + 2; c9008fc667 2012-08-08 kinaba: p_memo.resize(m+1); c9008fc667 2012-08-08 kinaba: p_memo_set.resize(m+1); c9008fc667 2012-08-08 kinaba: b_memo.resize(m+1); c9008fc667 2012-08-08 kinaba: b_memo_set.resize(m+1); c9008fc667 2012-08-08 kinaba: return is_possible(m) ? gain[best_num(m, NG)] : -1; c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: c9008fc667 2012-08-08 kinaba: vector<bool> p_memo; c9008fc667 2012-08-08 kinaba: vector<bool> p_memo_set; c9008fc667 2012-08-08 kinaba: bool is_possible(int state) c9008fc667 2012-08-08 kinaba: { c9008fc667 2012-08-08 kinaba: if(p_memo_set[state]) c9008fc667 2012-08-08 kinaba: return p_memo[state]; c9008fc667 2012-08-08 kinaba: p_memo_set[state] = true; c9008fc667 2012-08-08 kinaba: c9008fc667 2012-08-08 kinaba: vector<int> yoko = yoko_base, tate = tate_base, next; c9008fc667 2012-08-08 kinaba: int cnt = 0; c9008fc667 2012-08-08 kinaba: for(int i=0,m=1; i<NH; ++i,m*=3) c9008fc667 2012-08-08 kinaba: { c9008fc667 2012-08-08 kinaba: int v = (state/m)%3; c9008fc667 2012-08-08 kinaba: if( v == 1 ) { c9008fc667 2012-08-08 kinaba: int y = hats[i].first; c9008fc667 2012-08-08 kinaba: int x = hats[i].second; c9008fc667 2012-08-08 kinaba: yoko[y]++; c9008fc667 2012-08-08 kinaba: tate[x]++; c9008fc667 2012-08-08 kinaba: ++cnt; c9008fc667 2012-08-08 kinaba: } else if( v == 2 ) { c9008fc667 2012-08-08 kinaba: next.push_back(m); c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: if( next.empty() ) c9008fc667 2012-08-08 kinaba: { c9008fc667 2012-08-08 kinaba: if( cnt != NC ) c9008fc667 2012-08-08 kinaba: return false; c9008fc667 2012-08-08 kinaba: for(int y=0; y<yoko.size(); ++y) c9008fc667 2012-08-08 kinaba: if(yoko[y]%2 != 0) c9008fc667 2012-08-08 kinaba: return p_memo[state] = false; c9008fc667 2012-08-08 kinaba: for(int x=0; x<tate.size(); ++x) c9008fc667 2012-08-08 kinaba: if(tate[x]%2 != 0) c9008fc667 2012-08-08 kinaba: return p_memo[state] = false; c9008fc667 2012-08-08 kinaba: return p_memo[state] = true; c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: else c9008fc667 2012-08-08 kinaba: { c9008fc667 2012-08-08 kinaba: int m = next[0]; c9008fc667 2012-08-08 kinaba: int s[] = {state-2*m, state-m}; c9008fc667 2012-08-08 kinaba: return p_memo[state] = ( is_possible(s[0]) || is_possible(s[1]) ); c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: c9008fc667 2012-08-08 kinaba: vector<char> b_memo; c9008fc667 2012-08-08 kinaba: vector<bool> b_memo_set; c9008fc667 2012-08-08 kinaba: char best_num(int state, int guess) c9008fc667 2012-08-08 kinaba: { c9008fc667 2012-08-08 kinaba: if( guess==0 ) c9008fc667 2012-08-08 kinaba: return 0; c9008fc667 2012-08-08 kinaba: if(b_memo_set[state]) c9008fc667 2012-08-08 kinaba: return b_memo[state]; c9008fc667 2012-08-08 kinaba: b_memo_set[state] = true; c9008fc667 2012-08-08 kinaba: c9008fc667 2012-08-08 kinaba: char best = 0; c9008fc667 2012-08-08 kinaba: for(int i=0,m=1; i<NH; ++i,m*=3) c9008fc667 2012-08-08 kinaba: { c9008fc667 2012-08-08 kinaba: int v = (state/m)%3; c9008fc667 2012-08-08 kinaba: if( v == 2 ) c9008fc667 2012-08-08 kinaba: { c9008fc667 2012-08-08 kinaba: int s[] = {state-2*m, state-m}; c9008fc667 2012-08-08 kinaba: char score = 13; c9008fc667 2012-08-08 kinaba: if( is_possible(s[0]) ) c9008fc667 2012-08-08 kinaba: score = min(score, best_num(s[0], guess-1)); c9008fc667 2012-08-08 kinaba: if( is_possible(s[1]) ) c9008fc667 2012-08-08 kinaba: score = min<char>(score, best_num(s[1], guess-1)+1); c9008fc667 2012-08-08 kinaba: best = max(best, score); c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: return b_memo[state] = best; c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: }; c9008fc667 2012-08-08 kinaba: c9008fc667 2012-08-08 kinaba: // BEGIN CUT HERE c9008fc667 2012-08-08 kinaba: #include <ctime> c9008fc667 2012-08-08 kinaba: double start_time; string timer() c9008fc667 2012-08-08 kinaba: { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } c9008fc667 2012-08-08 kinaba: template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) c9008fc667 2012-08-08 kinaba: { os << "{ "; c9008fc667 2012-08-08 kinaba: for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it) c9008fc667 2012-08-08 kinaba: os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } c9008fc667 2012-08-08 kinaba: void verify_case(const int& Expected, const int& Received) { c9008fc667 2012-08-08 kinaba: bool ok = (Expected == Received); c9008fc667 2012-08-08 kinaba: if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; c9008fc667 2012-08-08 kinaba: cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } c9008fc667 2012-08-08 kinaba: #define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); c9008fc667 2012-08-08 kinaba: #define END verify_case(_, MagicalHats().findMaximumReward(board, coins, numGuesses));} c9008fc667 2012-08-08 kinaba: int main(){ c9008fc667 2012-08-08 kinaba: c9008fc667 2012-08-08 kinaba: CASE(0) c9008fc667 2012-08-08 kinaba: string board_[] = {"H"}; c9008fc667 2012-08-08 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); c9008fc667 2012-08-08 kinaba: int coins_[] = {1}; c9008fc667 2012-08-08 kinaba: vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); c9008fc667 2012-08-08 kinaba: int numGuesses = 1; c9008fc667 2012-08-08 kinaba: int _ = 1; c9008fc667 2012-08-08 kinaba: END c9008fc667 2012-08-08 kinaba: CASE(1) c9008fc667 2012-08-08 kinaba: string board_[] = {"HHH", c9008fc667 2012-08-08 kinaba: "H.H", c9008fc667 2012-08-08 kinaba: "HH."}; c9008fc667 2012-08-08 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); c9008fc667 2012-08-08 kinaba: int coins_[] = {9}; c9008fc667 2012-08-08 kinaba: vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); c9008fc667 2012-08-08 kinaba: int numGuesses = 1; c9008fc667 2012-08-08 kinaba: int _ = 9; c9008fc667 2012-08-08 kinaba: END c9008fc667 2012-08-08 kinaba: CASE(2) c9008fc667 2012-08-08 kinaba: string board_[] = {"HH", c9008fc667 2012-08-08 kinaba: "HH"}; c9008fc667 2012-08-08 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); c9008fc667 2012-08-08 kinaba: int coins_[] = {1,2,3,4}; c9008fc667 2012-08-08 kinaba: vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); c9008fc667 2012-08-08 kinaba: int numGuesses = 3; c9008fc667 2012-08-08 kinaba: int _ = 6; c9008fc667 2012-08-08 kinaba: END c9008fc667 2012-08-08 kinaba: CASE(3) c9008fc667 2012-08-08 kinaba: string board_[] = {"HHH", c9008fc667 2012-08-08 kinaba: "HHH", c9008fc667 2012-08-08 kinaba: "H.H"}; c9008fc667 2012-08-08 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); c9008fc667 2012-08-08 kinaba: int coins_[] = {13,13,13,13}; c9008fc667 2012-08-08 kinaba: vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); c9008fc667 2012-08-08 kinaba: int numGuesses = 2; c9008fc667 2012-08-08 kinaba: int _ = 13; c9008fc667 2012-08-08 kinaba: END c9008fc667 2012-08-08 kinaba: CASE(4) c9008fc667 2012-08-08 kinaba: string board_[] = {"HHH", c9008fc667 2012-08-08 kinaba: "HHH", c9008fc667 2012-08-08 kinaba: "H.H"}; c9008fc667 2012-08-08 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); c9008fc667 2012-08-08 kinaba: int coins_[] = {13,13,13,13}; c9008fc667 2012-08-08 kinaba: vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); c9008fc667 2012-08-08 kinaba: int numGuesses = 3; c9008fc667 2012-08-08 kinaba: int _ = 26; c9008fc667 2012-08-08 kinaba: END c9008fc667 2012-08-08 kinaba: CASE(5) c9008fc667 2012-08-08 kinaba: string board_[] = {"H.H.", c9008fc667 2012-08-08 kinaba: ".H.H", c9008fc667 2012-08-08 kinaba: "H.H."}; c9008fc667 2012-08-08 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); c9008fc667 2012-08-08 kinaba: int coins_[] = {17}; c9008fc667 2012-08-08 kinaba: vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); c9008fc667 2012-08-08 kinaba: int numGuesses = 6; c9008fc667 2012-08-08 kinaba: int _ = -1; c9008fc667 2012-08-08 kinaba: END c9008fc667 2012-08-08 kinaba: CASE(6) c9008fc667 2012-08-08 kinaba: string board_[] = {"HHH..........", c9008fc667 2012-08-08 kinaba: "H.H..........", c9008fc667 2012-08-08 kinaba: "HHH..........", c9008fc667 2012-08-08 kinaba: "H.H..........", c9008fc667 2012-08-08 kinaba: "HHH.........." c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: }; c9008fc667 2012-08-08 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); c9008fc667 2012-08-08 kinaba: int coins_[] = {33,337,1007,2403,5601,6003,9999}; c9008fc667 2012-08-08 kinaba: vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); c9008fc667 2012-08-08 kinaba: int numGuesses = 5; c9008fc667 2012-08-08 kinaba: int _ = 1377; c9008fc667 2012-08-08 kinaba: END c9008fc667 2012-08-08 kinaba: CASE(7) c9008fc667 2012-08-08 kinaba: string board_[] = {".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".....H.H.....", c9008fc667 2012-08-08 kinaba: "......H......", c9008fc667 2012-08-08 kinaba: ".....H.H.....", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: ".............", c9008fc667 2012-08-08 kinaba: "............."}; c9008fc667 2012-08-08 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); c9008fc667 2012-08-08 kinaba: int coins_[] = {22}; c9008fc667 2012-08-08 kinaba: vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); c9008fc667 2012-08-08 kinaba: int numGuesses = 3; c9008fc667 2012-08-08 kinaba: int _ = 22; c9008fc667 2012-08-08 kinaba: END c9008fc667 2012-08-08 kinaba: /* c9008fc667 2012-08-08 kinaba: CASE(8) c9008fc667 2012-08-08 kinaba: string board_[] = ; c9008fc667 2012-08-08 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); c9008fc667 2012-08-08 kinaba: int coins_[] = ; c9008fc667 2012-08-08 kinaba: vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); c9008fc667 2012-08-08 kinaba: int numGuesses = ; c9008fc667 2012-08-08 kinaba: int _ = ; c9008fc667 2012-08-08 kinaba: END c9008fc667 2012-08-08 kinaba: CASE(9) c9008fc667 2012-08-08 kinaba: string board_[] = ; c9008fc667 2012-08-08 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); c9008fc667 2012-08-08 kinaba: int coins_[] = ; c9008fc667 2012-08-08 kinaba: vector <int> coins(coins_, coins_+sizeof(coins_)/sizeof(*coins_)); c9008fc667 2012-08-08 kinaba: int numGuesses = ; c9008fc667 2012-08-08 kinaba: int _ = ; c9008fc667 2012-08-08 kinaba: END c9008fc667 2012-08-08 kinaba: */ c9008fc667 2012-08-08 kinaba: } c9008fc667 2012-08-08 kinaba: // END CUT HERE