#include #include using namespace std; #define REP(i,a,n) for(int i=(a); i<(int)(n); i++) #define rep(i,n) REP(i,0,n) #define FOR(it,c) for(__typeof((c).begin()) it=(c).begin(); it!=(c).end(); ++it) #define ALLOF(c) (c).begin(), (c).end() typedef long long ll; typedef unsigned long long ull; unsigned int xor128(){ static unsigned int x=123456789, y=362436069, z=521288629, w=88675123; unsigned int t; t=(x^(x<<11)); x=y; y=z; z=w; return w=(w^(w>>19))^(t^(t>>8)); } inline double frand(){ return xor128()%UINT_MAX/static_cast(UINT_MAX); } class Timer { double start_time; double get_now(){ struct timeval t; gettimeofday(&t, NULL); return t.tv_sec + t.tv_usec * 1e-6; } public: void start(){ start_time = get_now(); } double sec(){ return get_now()-start_time; } }; class Solver5002 { Timer timer; const double time_limit = 0.98; //const double time_limit = 9.5; const int vx[4] = {1,0,-1,0}; const int vy[4] = {0,1,0,-1}; struct POS { int y, x, a; }; int N, K; vector L; vector> A; double base_score, score, best_score; vector vpos, best_vpos; double iscore(int len, const vector& parts, const vector& prev, const vector& next){ double ret = 0; rep(i,len){ if(parts[i]%2==1){ ret += 1.0; }else{ if(prev[i]%2==1 && next[i]%2==1) ret += 0.5; else ret -= 10.0; } } return ret; } void init(){ base_score = 0; rep(y,N){ rep(x,N){ if(A[y][x]%2==0) base_score++; } } vector lenp; map> lenm; rep(i,K) lenm[L[i]].push_back(i); FOR(it,lenm){ if(it->first > 2) continue; rep(i,(it->second).size()){ lenp.push_back((it->second)[i]); } (it->second).clear(); } while(true){ bool flg = true; FOR(it,lenm){ if((it->second).size() > 0){ lenp.push_back((it->second).back()); (it->second).pop_back(); flg = false; } } if(flg) break; } reverse(ALLOF(lenp)); vpos = vector(K); vector prev(30,0); vector parts(30,0); vector next(30,0); rep(tt, K){ int t = lenp[tt]; double best_score = -1e18; int best_y = 0, best_x = 0, which = 0; rep(y,N){ rep(x,N){ if(x+L[t]=0) prev[i] = A[y-1][x+i]; else prev[i] = parts[i]; if(y+1=0) prev[i] = A[y+i][x-1]; else prev[i] = parts[i]; if(x+1(N,0)) { timer.start(); } void setL(int i, int v){ L[i] = v; } void setA(int i, int j, int v){ A[i][j] = v; } void solve(){ cerr << timer.sec() << endl; init(); double start_sec = timer.sec(); cerr << start_sec << endl; int cnt = 0; int acnt = 0; while(true){ double sec = timer.sec(); if(sec > time_limit) break; double T = calcTemp(sec-start_sec, time_limit-start_sec); cnt++; int prev_score = score; int si = xor128()%K; POS pos = vpos[si]; POS npos; { int ra = xor128()%2; //int ra = cnt%2; int W = N - vx[ra]*(L[si]-1); int H = N - vy[ra]*(L[si]-1); int x = xor128()%W; int y = xor128()%H; /* while(true){ if(A[y][x]%2==1) break; else{ int cnt = 0; rep(k,2){ int nx = x + vx[(2*k+ra)%4]; int ny = y + vy[(2*k+ra)%4]; if(0<=nx && nx=1) break; } x = xor128()%W; y = xor128()%H; } */ npos.x = x; npos.y = y; npos.a = ra; } pswap(si, pos, npos); double delta = (score - prev_score); if(delta >= 0){ //acnt++; }else{ if(exp(delta / T) >= frand()){ //acnt++; }else{ pswap(si, npos, pos); } } if(best_score < score){ best_score = score; best_vpos = vpos; } //if(cnt%100==0) cerr << T << "\t\t" << score-base_score << "\t\t" << acnt/(double)cnt << endl;; } cerr << "last score: " << best_score-base_score << endl; cerr << "loop count: " << cnt << endl; /* rep(y,N){ rep(x,N){ cerr << A[y][x] << " "; } cerr << endl; } */ } void output(){ rep(i,K){ cout << best_vpos[i].y+1 << " "; cout << best_vpos[i].x+1 << " "; cout << best_vpos[i].y+1+vy[best_vpos[i].a]*(L[i]-1) << " "; cout << best_vpos[i].x+1+vx[best_vpos[i].a]*(L[i]-1) << endl; } } }; int main(){ ios::sync_with_stdio(false); int N, K; cin >> N >> K; Solver5002 solver(N, K); rep(i,K){ int l; cin >> l; solver.setL(i, l); } vector A; rep(i,N){ string a; cin >> a; rep(j,N){ if(a[j] == '0') solver.setA(i, j, 0); else solver.setA(i, j, 1); } } solver.solve(); solver.output(); return 0; }