5f23464ec4 2014-06-28 kinaba: #include <iostream> 5f23464ec4 2014-06-28 kinaba: #include <sstream> 5f23464ec4 2014-06-28 kinaba: #include <iomanip> 5f23464ec4 2014-06-28 kinaba: #include <vector> 5f23464ec4 2014-06-28 kinaba: #include <string> 5f23464ec4 2014-06-28 kinaba: #include <map> 5f23464ec4 2014-06-28 kinaba: #include <set> 5f23464ec4 2014-06-28 kinaba: #include <algorithm> 5f23464ec4 2014-06-28 kinaba: #include <numeric> 5f23464ec4 2014-06-28 kinaba: #include <iterator> 5f23464ec4 2014-06-28 kinaba: #include <functional> 5f23464ec4 2014-06-28 kinaba: #include <complex> 5f23464ec4 2014-06-28 kinaba: #include <queue> 5f23464ec4 2014-06-28 kinaba: #include <stack> 5f23464ec4 2014-06-28 kinaba: #include <cmath> 5f23464ec4 2014-06-28 kinaba: #include <cassert> 5f23464ec4 2014-06-28 kinaba: #include <tuple> 5f23464ec4 2014-06-28 kinaba: using namespace std; 5f23464ec4 2014-06-28 kinaba: typedef long long LL; 5f23464ec4 2014-06-28 kinaba: typedef complex<double> CMP; 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: template<typename Vert=int, typename Flow=int, int NV=2048> 5f23464ec4 2014-06-28 kinaba: class MaxFlow 5f23464ec4 2014-06-28 kinaba: { 5f23464ec4 2014-06-28 kinaba: vector<int> G[NV]; 5f23464ec4 2014-06-28 kinaba: Flow F[NV][NV]; 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: public: 5f23464ec4 2014-06-28 kinaba: void addEdge( Vert s, Vert t, Flow f ) 5f23464ec4 2014-06-28 kinaba: { 5f23464ec4 2014-06-28 kinaba: G[s].push_back(t); 5f23464ec4 2014-06-28 kinaba: G[t].push_back(s); 5f23464ec4 2014-06-28 kinaba: F[s][t] = f; 5f23464ec4 2014-06-28 kinaba: F[t][s] = 0; 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: Flow calc( Vert S, Vert D ) 5f23464ec4 2014-06-28 kinaba: { 5f23464ec4 2014-06-28 kinaba: for( Flow total=0 ;; ) { 5f23464ec4 2014-06-28 kinaba: // Do BFS and compute the level for each node. 5f23464ec4 2014-06-28 kinaba: int LV[NV] = {0}; 5f23464ec4 2014-06-28 kinaba: vector<int> Q(1, S); 5f23464ec4 2014-06-28 kinaba: for(int lv=1; !Q.empty(); ++lv) { 5f23464ec4 2014-06-28 kinaba: vector<int> Q2; 5f23464ec4 2014-06-28 kinaba: for(size_t i=0; i!=Q.size(); ++i) { 5f23464ec4 2014-06-28 kinaba: const vector<int>& ne = G[Q[i]]; 5f23464ec4 2014-06-28 kinaba: for(size_t j=0; j!=ne.size(); ++j) 5f23464ec4 2014-06-28 kinaba: if( F[Q[i]][ne[j]] && !LV[ne[j]] && ne[j]!=S ) 5f23464ec4 2014-06-28 kinaba: LV[ne[j]]=lv, Q2.push_back(ne[j]); 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: Q.swap(Q2); 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: // Destination is now unreachable. Done. 5f23464ec4 2014-06-28 kinaba: if( !LV[D] ) 5f23464ec4 2014-06-28 kinaba: return total; 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: // Iterating DFS. 5f23464ec4 2014-06-28 kinaba: bool blocked[NV] = {}; 5f23464ec4 2014-06-28 kinaba: total += dinic_dfs( S, D, LV, 0x7fffffff, blocked ); 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: private: 5f23464ec4 2014-06-28 kinaba: Flow dinic_dfs( int v, int D, int LV[], Flow flow_in, bool blocked[] ) 5f23464ec4 2014-06-28 kinaba: { 5f23464ec4 2014-06-28 kinaba: Flow flow_out = 0; 5f23464ec4 2014-06-28 kinaba: for(size_t i=0; i!=G[v].size(); ++i) { 5f23464ec4 2014-06-28 kinaba: int u = G[v][i]; 5f23464ec4 2014-06-28 kinaba: if( LV[v]+1==LV[u] && F[v][u] ) { 5f23464ec4 2014-06-28 kinaba: Flow f = min(flow_in-flow_out, F[v][u]); 5f23464ec4 2014-06-28 kinaba: if( u==D || !blocked[u] && (f=dinic_dfs(u,D,LV,f,blocked))>0 ) { 5f23464ec4 2014-06-28 kinaba: F[v][u] -= f; 5f23464ec4 2014-06-28 kinaba: F[u][v] += f; 5f23464ec4 2014-06-28 kinaba: flow_out += f; 5f23464ec4 2014-06-28 kinaba: if( flow_in == flow_out ) return flow_out; 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: blocked[v] = (flow_out==0); 5f23464ec4 2014-06-28 kinaba: return flow_out; 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: }; 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: class BlockTheBlockPuzzle { public: 5f23464ec4 2014-06-28 kinaba: int minimumHoles(vector <string> board) 5f23464ec4 2014-06-28 kinaba: { 5f23464ec4 2014-06-28 kinaba: const int H = board.size(); 5f23464ec4 2014-06-28 kinaba: const int W = board[0].size(); 5f23464ec4 2014-06-28 kinaba: const int INF = 2500; 5f23464ec4 2014-06-28 kinaba: for(int gy=0; gy<H; ++gy) 5f23464ec4 2014-06-28 kinaba: for(int gx=0; gx<W; ++gx) if(board[gy][gx] == '$') 5f23464ec4 2014-06-28 kinaba: { 5f23464ec4 2014-06-28 kinaba: map<pair<int,int>, int> id; 5f23464ec4 2014-06-28 kinaba: for(int y=gy%3; y<H; y+=3) 5f23464ec4 2014-06-28 kinaba: for(int x=gx%3; x<W; x+=3) 5f23464ec4 2014-06-28 kinaba: { 5f23464ec4 2014-06-28 kinaba: int new_id = id.size(); 5f23464ec4 2014-06-28 kinaba: id[make_pair(y,x)] = new_id; 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: int N = id.size(); 5f23464ec4 2014-06-28 kinaba: MaxFlow<>* mf = new MaxFlow<>; 5f23464ec4 2014-06-28 kinaba: enum {IN, OUT}; 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: int Goal; 5f23464ec4 2014-06-28 kinaba: vector<int> Start; 5f23464ec4 2014-06-28 kinaba: for(int y=gy%3; y<H; y+=3) 5f23464ec4 2014-06-28 kinaba: for(int x=gx%3; x<W; x+=3)if(board[y][x]!='H') 5f23464ec4 2014-06-28 kinaba: { 5f23464ec4 2014-06-28 kinaba: int v1 = id[make_pair(y,x)]; 5f23464ec4 2014-06-28 kinaba: if(board[y][x]=='$') 5f23464ec4 2014-06-28 kinaba: Goal = v1; 5f23464ec4 2014-06-28 kinaba: if(board[y][x]=='b') 5f23464ec4 2014-06-28 kinaba: Start.push_back(v1); 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: int e = (board[y][x]=='.' ? 1 : INF); 5f23464ec4 2014-06-28 kinaba: mf->addEdge(v1*2+IN, v1*2+OUT, e); 5f23464ec4 2014-06-28 kinaba: //cerr << v1 << " -- " << e << " -- " << v1 << endl; 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: const int dy[] = {+1,0}; 5f23464ec4 2014-06-28 kinaba: const int dx[] = {0,+1}; 5f23464ec4 2014-06-28 kinaba: for(int d=0; d<2; ++d) 5f23464ec4 2014-06-28 kinaba: { 5f23464ec4 2014-06-28 kinaba: int Y = y+dy[d]*3; 5f23464ec4 2014-06-28 kinaba: int X = x+dx[d]*3; 5f23464ec4 2014-06-28 kinaba: if(0<=Y&&Y<H&&0<=X&&X<W&&board[Y][X]!='H') 5f23464ec4 2014-06-28 kinaba: { 5f23464ec4 2014-06-28 kinaba: int v2 = id[make_pair(Y,X)]; 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: int y1=y+dy[d]*1; 5f23464ec4 2014-06-28 kinaba: int x1=x+dx[d]*1; 5f23464ec4 2014-06-28 kinaba: int y2=y+dy[d]*2; 5f23464ec4 2014-06-28 kinaba: int x2=x+dx[d]*2; 5f23464ec4 2014-06-28 kinaba: int e = INF; 5f23464ec4 2014-06-28 kinaba: if(board[y1][x1]!='b'&&board[y2][x2]!='b') 5f23464ec4 2014-06-28 kinaba: e = (board[y1][x1]=='.')+(board[y2][x2]=='.'); 5f23464ec4 2014-06-28 kinaba: if(e) { 5f23464ec4 2014-06-28 kinaba: mf->addEdge(v1*2+OUT, v2*2+IN, e); 5f23464ec4 2014-06-28 kinaba: mf->addEdge(v2*2+OUT, v1*2+IN, e); 5f23464ec4 2014-06-28 kinaba: //cerr << v1 << " -- " << e << " -- " << v2 << endl; 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: for(int v: Start) { 5f23464ec4 2014-06-28 kinaba: //cerr << "S: " << v << endl; 5f23464ec4 2014-06-28 kinaba: mf->addEdge(v*2+OUT, N*2+IN, INF); 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: //cerr << "G: " << Goal << endl; 5f23464ec4 2014-06-28 kinaba: int ans = mf->calc(Goal*2+OUT, N*2+IN); 5f23464ec4 2014-06-28 kinaba: delete mf; 5f23464ec4 2014-06-28 kinaba: return ans>=INF ? -1 : ans; 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: return -1; 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: }; 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: // BEGIN CUT HERE 5f23464ec4 2014-06-28 kinaba: #include <ctime> 5f23464ec4 2014-06-28 kinaba: double start_time; string timer() 5f23464ec4 2014-06-28 kinaba: { ostringstream os; os << " (" << int((clock()-start_time)/CLOCKS_PER_SEC*1000) << " msec)"; return os.str(); } 5f23464ec4 2014-06-28 kinaba: template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) 5f23464ec4 2014-06-28 kinaba: { os << "{ "; 5f23464ec4 2014-06-28 kinaba: for(typename vector<T>::const_iterator it=v.begin(); it!=v.end(); ++it) 5f23464ec4 2014-06-28 kinaba: os << '\"' << *it << '\"' << (it+1==v.end() ? "" : ", "); os << " }"; return os; } 5f23464ec4 2014-06-28 kinaba: void verify_case(const int& Expected, const int& Received) { 5f23464ec4 2014-06-28 kinaba: bool ok = (Expected == Received); 5f23464ec4 2014-06-28 kinaba: if(ok) cerr << "PASSED" << timer() << endl; else { cerr << "FAILED" << timer() << endl; 5f23464ec4 2014-06-28 kinaba: cerr << "\to: \"" << Expected << '\"' << endl << "\tx: \"" << Received << '\"' << endl; } } 5f23464ec4 2014-06-28 kinaba: #define CASE(N) {cerr << "Test Case #" << N << "..." << flush; start_time=clock(); 5f23464ec4 2014-06-28 kinaba: #define END verify_case(_, BlockTheBlockPuzzle().minimumHoles(board));} 5f23464ec4 2014-06-28 kinaba: int main(){ 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: CASE(0) 5f23464ec4 2014-06-28 kinaba: string board_[] = {"b..$", 5f23464ec4 2014-06-28 kinaba: "....", 5f23464ec4 2014-06-28 kinaba: "HHHH", 5f23464ec4 2014-06-28 kinaba: "HHHH"}; 5f23464ec4 2014-06-28 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 5f23464ec4 2014-06-28 kinaba: int _ = 2; 5f23464ec4 2014-06-28 kinaba: END 5f23464ec4 2014-06-28 kinaba: CASE(1) 5f23464ec4 2014-06-28 kinaba: string board_[] = {"............H..", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "HHH$HHH.....H..", 5f23464ec4 2014-06-28 kinaba: "HHHHHHH........", 5f23464ec4 2014-06-28 kinaba: "HHHHHHHH.......", 5f23464ec4 2014-06-28 kinaba: "......b..H.....", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...H..H..H.....", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "..............."}; 5f23464ec4 2014-06-28 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 5f23464ec4 2014-06-28 kinaba: int _ = 0; 5f23464ec4 2014-06-28 kinaba: END 5f23464ec4 2014-06-28 kinaba: CASE(2) 5f23464ec4 2014-06-28 kinaba: string board_[] = {"............H..", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "HHH$HHH........", 5f23464ec4 2014-06-28 kinaba: "HHHHHHH........", 5f23464ec4 2014-06-28 kinaba: "HHHHHHHH.......", 5f23464ec4 2014-06-28 kinaba: "......b..H.....", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...H..H..H.....", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "...............", 5f23464ec4 2014-06-28 kinaba: "..............."}; 5f23464ec4 2014-06-28 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 5f23464ec4 2014-06-28 kinaba: int _ = 1; 5f23464ec4 2014-06-28 kinaba: END 5f23464ec4 2014-06-28 kinaba: CASE(3) 5f23464ec4 2014-06-28 kinaba: string board_[] = {"b..$...", 5f23464ec4 2014-06-28 kinaba: "...H...", 5f23464ec4 2014-06-28 kinaba: ".......", 5f23464ec4 2014-06-28 kinaba: "b..b..b", 5f23464ec4 2014-06-28 kinaba: "...H...", 5f23464ec4 2014-06-28 kinaba: ".......", 5f23464ec4 2014-06-28 kinaba: "b..b..b"} 5f23464ec4 2014-06-28 kinaba: 5f23464ec4 2014-06-28 kinaba: ; 5f23464ec4 2014-06-28 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 5f23464ec4 2014-06-28 kinaba: int _ = 4; 5f23464ec4 2014-06-28 kinaba: END 5f23464ec4 2014-06-28 kinaba: CASE(4) 5f23464ec4 2014-06-28 kinaba: string board_[] = {"b..b..b", 5f23464ec4 2014-06-28 kinaba: "..b..b.", 5f23464ec4 2014-06-28 kinaba: ".......", 5f23464ec4 2014-06-28 kinaba: "b..$bbb", 5f23464ec4 2014-06-28 kinaba: ".b.....", 5f23464ec4 2014-06-28 kinaba: "....b..", 5f23464ec4 2014-06-28 kinaba: "b..b..b"} 5f23464ec4 2014-06-28 kinaba: ; 5f23464ec4 2014-06-28 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 5f23464ec4 2014-06-28 kinaba: int _ = -1; 5f23464ec4 2014-06-28 kinaba: END 5f23464ec4 2014-06-28 kinaba: /* 5f23464ec4 2014-06-28 kinaba: CASE(5) 5f23464ec4 2014-06-28 kinaba: string board_[] = ; 5f23464ec4 2014-06-28 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 5f23464ec4 2014-06-28 kinaba: int _ = ; 5f23464ec4 2014-06-28 kinaba: END 5f23464ec4 2014-06-28 kinaba: CASE(6) 5f23464ec4 2014-06-28 kinaba: string board_[] = ; 5f23464ec4 2014-06-28 kinaba: vector <string> board(board_, board_+sizeof(board_)/sizeof(*board_)); 5f23464ec4 2014-06-28 kinaba: int _ = ; 5f23464ec4 2014-06-28 kinaba: END 5f23464ec4 2014-06-28 kinaba: */ 5f23464ec4 2014-06-28 kinaba: } 5f23464ec4 2014-06-28 kinaba: // END CUT HERE