#pragma GCC optimize("O3,unroll-loops") #pragma GCC target("avx2,bmi,bmi2,lzcnt,popcnt") #include #include #include #include using namespace std; struct Xorshift { uint32_t x = 123456789; uint32_t y = 362436069; uint32_t z = 521288629; uint32_t w = 88675123; inline uint32_t next() { uint32_t t = x ^ (x << 11); x = y; y = z; z = w; return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); } inline double nextDouble() { return next() / 4294967296.0; } inline int nextInt(int L, int R) { return L + next() % (R - L + 1); } }; int N, T_max; int A[400]; int adj[400][4]; int adj_deg[400]; struct State { int path[400]; int len; bool visited[400]; int score; inline void init() { len = 0; score = 0; for(int i = 0; i < 400; ++i) visited[i] = false; } inline void push(int u) { path[len++] = u; visited[u] = true; score += A[u]; } inline int pop() { int u = path[--len]; visited[u] = false; score -= A[u]; return u; } }; State generate_initial(Xorshift& rnd) { State best; best.score = -1; for(int i = 0; i < 5000; ++i) { State s; s.init(); int start = rnd.nextInt(0, N * N - 1); s.push(start); while(s.len < T_max) { int u = s.path[s.len - 1]; int best_v = -1; int max_a = -1; int cands[4]; int cands_sz = 0; for(int k = 0; k < adj_deg[u]; ++k) { int v = adj[u][k]; if(!s.visited[v]) { cands[cands_sz++] = v; if(A[v] > max_a) { max_a = A[v]; best_v = v; } } } if(cands_sz == 0) break; int nxt; if(rnd.nextDouble() < 0.8 && best_v != -1) { nxt = best_v; } else { nxt = cands[rnd.nextInt(0, cands_sz - 1)]; } s.push(nxt); } if(s.score > best.score) best = s; } return best; } inline void mutate(State& s, Xorshift& rnd) { if(s.len > 1 && rnd.nextDouble() < 0.5) { int half = s.len / 2; for(int i = 0; i < half; ++i) { int tmp = s.path[i]; s.path[i] = s.path[s.len - 1 - i]; s.path[s.len - 1 - i] = tmp; } } if(s.len > 1) { double r = rnd.nextDouble(); int pop_len = 1 + (int)(r * r * (s.len - 1)); if(pop_len > s.len - 1) pop_len = s.len - 1; for(int i = 0; i < pop_len; ++i) { s.pop(); } } while(s.len < T_max) { int u = s.path[s.len - 1]; int best_v = -1; int max_a = -1; int cands[4]; int cands_sz = 0; for(int k = 0; k < adj_deg[u]; ++k) { int v = adj[u][k]; if(!s.visited[v]) { cands[cands_sz++] = v; if(A[v] > max_a) { max_a = A[v]; best_v = v; } } } if(cands_sz == 0) break; int nxt; if(rnd.nextDouble() < 0.7 && best_v != -1) { nxt = best_v; } else { nxt = cands[rnd.nextInt(0, cands_sz - 1)]; } s.push(nxt); } } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); if (!(cin >> N >> T_max)) return 0; for(int i = 0; i < N * N; ++i) { cin >> A[i]; } for(int i = 0; i < N; ++i) { for(int j = 0; j < N; ++j) { int u = i * N + j; adj_deg[u] = 0; if(i > 0) adj[u][adj_deg[u]++] = (i - 1) * N + j; if(i < N - 1) adj[u][adj_deg[u]++] = (i + 1) * N + j; if(j > 0) adj[u][adj_deg[u]++] = i * N + j - 1; if(j < N - 1) adj[u][adj_deg[u]++] = i * N + j + 1; } } Xorshift rnd; auto start_clock = chrono::steady_clock::now(); double start_time = chrono::duration_cast(start_clock.time_since_epoch()).count() * 1e-9; double time_limit = 1.99; State cur = generate_initial(rnd); State best = cur; double T0 = 5000.0; double T1 = 10.0; int iter = 0; double current_time = 0.0; while(true) { if((iter & 1023) == 0) { auto now_clock = chrono::steady_clock::now(); current_time = chrono::duration_cast(now_clock.time_since_epoch()).count() * 1e-9 - start_time; if(current_time > time_limit) break; } iter++; State nxt = cur; mutate(nxt, rnd); int diff = nxt.score - cur.score; if(diff >= 0) { cur = nxt; if(cur.score > best.score) { best = cur; } } else { double progress = current_time / time_limit; double temp = T0 * pow(T1 / T0, progress); if(rnd.nextDouble() < exp(diff / temp)) { cur = nxt; } } } cout << best.len << "\n"; for(int i = 0; i < best.len; ++i) { cout << best.path[i] / N << " " << best.path[i] % N << "\n"; } return 0; }