#include using namespace std; using pii=pair; using tii=tuple; using qii=tuple; using ll=long long; using ull=unsigned long long; using ld=long double; constexpr int INF=1e9; constexpr ll INF_ll=1e18; #define rep(i,n) for (int i=0;i<(int)(n);i++) #define replr(i,l,r) for (int i=(int)(l);i<(int)(r);i++) #define all(v) v.begin(),v.end() #define len(v) ((int)v.size()) template inline bool chmin(T &a,T b){ if(a>b){ a=b; return true; } return false; } template inline bool chmax(T &a,T b){ if(a inline bool chmin_ref(T &a,const T &b){ if(a>b){ a=b; return true; } return false; } template inline bool chmax_ref(T &a,const T &b){ if(a(now-start).count(); return ms; } int get_ms_all_program(){ auto now=chrono::steady_clock::now(); int ms=chrono::duration_cast(now-program_start).count(); return ms; } } mt19937 mt; uint32_t rand_int(uint32_t r){ //[0,r) assert(r!=0); return ((uint64_t)mt()*r)>>32; } int rand_int(int l,int r){ //[l,r) assert(l T get_random_element(const vector &v){ assert(!v.empty()); return v[rand_int(len(v))]; } template void add(vector &a,vector b){ for(auto i:b) a.push_back(i); } struct union_find{ int n,now_comp_cnt; vector par,sz,min_v; union_find(int n_):n(n_),now_comp_cnt(n_),par(n),sz(n,1),min_v(n){ for(int i=0;i all_size(){ vector cnt(n,0); for(int i=0;i ret; for(int i=0;i> all_comp(){ vector> comp(n); for(int i=0;i> ret(now_comp_cnt); for(int i=0;i P; array,N*N> G; array B; array,N*N> A; int one(int i,int j){ return i*N+j; } pii two(int x){ return {x/N,x%N}; } namespace Solver{ //https://eijirou-kyopro.hatenablog.com/entry/2024/02/01/115639 constexpr int W=10000,tour_capacity=-1,hash_map_capacity=50*W; using Hash=uint32_t; using Score=int; array grid_hash; template struct Hash_Map{ uint32_t n; vector valid; vector> data; Hash_Map(int n_):n(n_),valid(n,false),data(n){} pair get_index(Key key) const{ Key i=key%n; while(valid[i]){ if(data[i].first==key){ return {true,i}; } i++; if(i==n) i=0; } return {false,i}; } void set(int i,Key key,T value){ assert(0<=i&&i<(int)n); valid[i]=true; data[i]={key,value}; } T get(int i) const{ assert(valid[i]); return data[i].second; } void clear(){ fill(all(valid),false); } }; struct Action{ int dir=0; auto operator==(const Action &other) const{ return dir==other.dir; } }; struct Evaluator{ int score=0; Hash hash=0; Evaluator(int score_,Hash hash_):score(score_),hash(hash_){} Score get_score() const{ return -score; } /*auto operator<=>(const Evaluator &other) const{ return this->get_score()<=>other.get_score(); }*/ }; struct Candidate{ int parent=-1; Action action; Evaluator evaluator; Candidate(int parent_,const Action action_,Evaluator evaluator_):parent(parent_),action(action_),evaluator(evaluator_){} }; #include using max_segtree=atcoder::segtree,[](pair a,pair b){return max(a,b);},[](){return pair{numeric_limits::lowest(),-INF};}>; struct Selector{ bool fill=false; vector candidate_v; max_segtree seg; vector> score_v; //{score,index}を管理 Hash_Map hash_to_index; Selector():seg(W),score_v(W),hash_to_index(hash_map_capacity){ rep(i,W) score_v[i]={-INF,i}; } void push(const Candidate &candidate){ const Hash hash=candidate.evaluator.hash; const Score score=candidate.evaluator.get_score(); if(fill&&seg.all_prod().first<=score) return; auto [valid,i]=hash_to_index.get_index(hash); if(valid){ int j=hash_to_index.get(i); if(hash==candidate_v[j].evaluator.hash){ if(fill){ if(score get_candidate_v(){ return candidate_v; } Candidate get_best_candidate(){ int best_idx=0; if(fill){ rep(i,W){ if(seg.get(i).first vis; State(){ vis.fill(false); vis[0]=true; } Evaluator calc_first_evaluator(){ return Evaluator(0,0); } void push_candidates(Selector &selector,const Evaluator &parent_evaluator,int parent){ rep(k,4){ int to=G[pos][k]; if(to==-1) continue; if(vis[to]) continue; vis[to]^=1; int b=0,cnt=0; rep(i,9){ if(A[to][i]!=-1&&!vis[A[to][i]]){ b|=1<> pre_tour,new_tour; vector leaf_eval_v; vector>> bucket_v; vector direct_load; Tree(){ if(tour_capacity!=-1){ pre_tour.reserve(tour_capacity); new_tour.reserve(tour_capacity); } leaf_eval_v.reserve(W); bucket_v.assign(W,{}); } void dfs(Selector &selector){ if(pre_tour.empty()){ state.push_candidates(selector,first_evaluator,-1); return; } for(auto [leaf_idx,action]:pre_tour){ if(0<=leaf_idx){ state.advance(action); state.push_candidates(selector,leaf_eval_v[leaf_idx],leaf_idx); state.undo(action); }else if(leaf_idx==-1){ state.advance(action); }else{ state.undo(action); } } } void update(const vector &candidate_v){ leaf_eval_v.clear(); if(pre_tour.empty()){ for(const auto &candidate:candidate_v){ pre_tour.emplace_back(len(leaf_eval_v),candidate.action); leaf_eval_v.emplace_back(candidate.evaluator); } return; } for(const auto &candidate:candidate_v){ bucket_v[candidate.parent].emplace_back(candidate.action,candidate.evaluator); } int idx=0; for(;pre_tour[idx].first==-1&&pre_tour[idx].second==pre_tour.back().second;idx++){ assert(pre_tour.back().first==-2); state.advance(pre_tour[idx].second); direct_load.push_back(pre_tour[idx].second); pre_tour.pop_back(); } for(;idx get_action_path(int parent){ vector ret=direct_load; for(auto [leaf_idx,action]:pre_tour){ if(0<=leaf_idx){ if(leaf_idx==parent){ ret.push_back(action); return ret; } }else if(leaf_idx==-1){ ret.push_back(action); }else{ ret.pop_back(); } } assert(0); } }; vector beam_search(){ Tree tree; Selector selector; vector ret; int best_score=0; rep(t,T-1){ tree.dfs(selector); vector candidate_v=selector.get_candidate_v(); if(candidate_v.empty()) break; Candidate best_candidate=selector.get_best_candidate(); //cerr << t << " " << len(selector.candidate_v) << " " << best_candidate.evaluator.get_score() << endl; if(1<=t){ vector action_v=tree.get_action_path(best_candidate.parent); action_v.push_back(best_candidate.action); if(chmax(best_score,best_candidate.evaluator.score)) ret=action_v; } tree.update(candidate_v); selector.clear(); } cerr << best_score << endl; return ret; } void solve(){ rep(i,N*N) grid_hash[i]=mt(); vector ans=beam_search(); cout << len(ans)+1 << '\n'; int pos=0; cout << "0 0\n"; for(auto action:ans){ pos=G[pos][action.dir]; auto [i,j]=two(pos); cout << i << ' ' << j << '\n'; } } } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); Timer::program_start_snap(); int n; cin >> n >> T; assert(n==N); rep(i,N*N){ cin >> P[i]; } rep(i,N*N) G[i].fill(-1); rep(i,N){ rep(j,N){ if(j+1 grid(9); rep(i,9) grid[i]=b&(1< pi={-1,-1,-1,0,0,0,1,1,1},pj={-1,0,1,-1,0,1,-1,0,1}; rep(i,N){ rep(j,N){ A[one(i,j)].fill(-1); rep(k,9){ int ti=i+pi[k],tj=j+pj[k]; if(ti<0||N<=ti||tj<0||N<=tj) continue; A[one(i,j)][k]=one(ti,tj); } } } Solver::solve(); exit(0); }