#include using namespace std; using pii=pair; using tii=tuple; using qii=tuple; using ll=long long; using ld=long double; const int INF=1e9; #define rep(i,n) for (int i=0;i<(int)(n);i++) #define all(v) v.begin(),v.end() template void chmin(T &a,T b){ if(a>b){ a=b; } } template void chmax(T &a,T b){ if(a A; struct bomb_info{ int C,L; vector a,b; }; vector bomb; int to(int i,int j){ return i*N+j; } int to(pii x){ return to(x.first,x.second); } pii back(int x){ int i=x/N; return {i,x-i*N}; } bool outside(int i,int j){ if(i<0||N<=i||j<0||N<=j) return true; return false; } void output_answer(vector &ans){ cout << (int)ans.size() << '\n'; for(auto &[s,t]:ans){ if(s==1) cout << s << ' ' << char(t) << '\n'; else cout << s << ' ' << t+1 << '\n'; } } struct Solver{ vector bomb_v; vector shop_idx; int can_bomb=5; vector> near_shop_dist(int k_th){ vector> ave(N,vector(N)); rep(si,N){ rep(sj,N){ vector v; for(auto &ij:bomb_v){ int i,j; tie(i,j)=back(ij); v.push_back(abs(i-si)+abs(j-sj)); } sort(all(v)); int sum=0,k=1.0; rep(i,k_th){ sum+=double(v[i])*k; k-=0.1; } ave[si][sj]=double(sum)/double(k_th); } } return ave; } vector ok_bomb; vector bomb_cover(vector> ave){ vector> bomb_sort(M); rep(i,M){ bomb_sort[i]={double(bomb[i].C)/double(bomb[i].L),i}; } sort(all(bomb_sort)); ok_bomb.resize(M,0); rep(i,can_bomb) ok_bomb[bomb_sort[i].second]=1; vector now_grid=A; vector ret; while(true){ double min_score=INF; pii max_cover={-1,-1}; rep(i,N){ rep(j,N){ rep(bomb_idx,M){ if(ok_bomb[bomb_idx]==0) continue; int cnt=0; rep(k,bomb[bomb_idx].L){ int ti=i+bomb[bomb_idx].a[k],tj=j+bomb[bomb_idx].b[k]; if(outside(ti,tj)) continue; if(now_grid[ti][tj]!='.') cnt++; } double now_score=INF; if(0 pi={0,1,0,-1},pj={1,0,-1,0}; int root_cost(int a,int b,vector &grid,int bomb_cnt){ int ai,aj,bi,bj; tie(ai,aj)=back(a); tie(bi,bj)=back(b); vector> dist(N,vector(N,INF)); dist[ai][aj]=0; priority_queue,vector>,greater>> pq; pq.push({0,{ai,aj}}); while(!pq.empty()){ int d; pii ij; tie(d,ij)=pq.top(); pq.pop(); int i,j; tie(i,j)=ij; if(dist[i][j] &grid,int bomb_cnt){ int ai,aj,bi,bj; tie(ai,aj)=back(a); tie(bi,bj)=back(b); vector> dist(N,vector(N,INF)); dist[ai][aj]=0; vector> prev(N,vector(N)); priority_queue,vector>,greater>> pq; pq.push({0,{ai,aj}}); while(!pq.empty()){ int d; pii ij; tie(d,ij)=pq.top(); pq.pop(); int i,j; tie(i,j)=ij; if(dist[i][j] &ans){ int ni=0,nj=0; vector bomb_cnt(M,0); int b=0; vector now_grid=A; int c=0; for(auto &[s,t]:ans){ if(s==1){ if(char(t)=='L') nj--; else if(char(t)=='R') nj++; else if(char(t)=='U') ni--; else if(char(t)=='D') ni++; else assert(0); assert(!outside(ni,nj)); if(now_grid[ni][nj]=='.') c+=(b+1)*(b+1); else c+=2*(b+1)*(b+1); }else if(s==2){ assert(now_grid[ni][nj]=='@'); int y=t; assert(0<=y&&y<=M-1); bomb_cnt[y]++; b++; c+=bomb[y].C; }else if(s==3){ int z=t; assert(0<=z&&z<=M-1); assert(1<=bomb_cnt[z]); bomb_cnt[z]--; b--; rep(k,bomb[z].L){ int ti=ni+bomb[z].a[k],tj=nj+bomb[z].b[k]; if(outside(ti,tj)) continue; now_grid[ti][tj]='.'; } }else{ assert(0); } } rep(i,N){ rep(j,N){ if(now_grid[i][j]!='.'){ return 1; } } } return max(10ll,1000000000000ll/(10000+c)); } vector cover_to_ans(vector &cover_v){ vector now_grid=A; vector now_ans; int now=0; int shop_cnt=0; rep(i,N){ rep(j,N){ if(A[i][j]=='@') shop_cnt++; } } int bomb_cnt=0; set last_shop_set; rep(t,int(cover_v.size())){ int idx,now_bomb_idx; tie(idx,now_bomb_idx)=cover_v[t]; int idx_i,idx_j; tie(idx_i,idx_j)=back(idx); int before_shop_cnt=shop_cnt; rep(k,bomb[now_bomb_idx].L){ int ti=idx_i+bomb[now_bomb_idx].a[k],tj=idx_j+bomb[now_bomb_idx].b[k]; if(outside(ti,tj)) continue; if(now_grid[ti][tj]=='@') shop_cnt--; } if(shop_cnt==0&&!last_shop_set.count(cover_v[t])){ last_shop_set.insert(cover_v[t]); shop_cnt=before_shop_cnt; cover_v.push_back(cover_v[t]); cover_v.erase(cover_v.begin()+t); t--; continue; } pii mn={INF,INF}; for(auto &x:bomb_v){ int i,j; tie(i,j)=back(x); if(now_grid[i][j]=='@') chmin(mn,{root_cost(now,x,now_grid,bomb_cnt),x}); } if(mn.first!=INF){ for(auto &i:root(now,mn.second,now_grid,bomb_cnt)){ now_ans.push_back({1,i}); } now=mn.second; int i,j; tie(i,j)=back(mn.second); if(shop_cnt==0){ for(int k=t;k cover_v,vector>> &shop_explosion){ vector shop_ok(int(bomb_v.size()),1); int now=0; int shop_cnt=int(bomb_v.size()); int bomb_cnt=0; set last_shop_set; int ret=0; rep(t,int(cover_v.size())){ int idx,now_bomb_idx; tie(idx,now_bomb_idx)=cover_v[t]; int idx_i,idx_j; tie(idx_i,idx_j)=back(idx); int before_shop_cnt=shop_cnt; for(auto &ij:shop_explosion[idx][now_bomb_idx]){ if(shop_ok[shop_idx[ij]]==1){ shop_cnt--; } } if(shop_cnt==0&&!last_shop_set.count(cover_v[t])){ last_shop_set.insert(cover_v[t]); shop_cnt=before_shop_cnt; cover_v.push_back(cover_v[t]); cover_v.erase(cover_v.begin()+t); t--; continue; } pii mn={INF,INF}; for(auto &x:bomb_v){ if(shop_ok[shop_idx[x]]==1) chmin(mn,{fake_root_cost(now,x,bomb_cnt),x}); } if(mn.first!=INF){ ret+=mn.first; now=mn.second; int i,j; tie(i,j)=back(mn.second); if(shop_cnt==0){ for(int k=t;k cover_v=bomb_cover(near_shop_dist(5)); int block_size=50/3; sort(cover_v.begin(),cover_v.end(), [&](pii i,pii j){ int il,ir,jl,jr; tie(il,ir)=back(i.first); tie(jl,jr)=back(j.first); int block_i=il/block_size,block_j=jl/block_size; if(block_i!=block_j) return iljr; else return ir>> shop_explosion(N*N,vector>(M)); rep(i,N){ rep(j,N){ rep(bomb_idx,M){ if(ok_bomb[bomb_idx]==0) continue; rep(k,bomb[bomb_idx].L){ int ti=i+bomb[bomb_idx].a[k],tj=j+bomb[bomb_idx].b[k]; if(outside(ti,tj)) continue; if(A[ti][tj]=='@') shop_explosion[to(i,j)][bomb_idx].push_back(to(ti,tj)); } } } } vector min_cost_cover_v=cover_v; int min_cost=fake_cost(min_cost_cover_v,shop_explosion); int cover_size=min_cost_cover_v.size(); while(true){ auto now=chrono::system_clock::now(); int ms=chrono::duration_cast(now-start).count(); if(2600<=ms) break; if(mt()%2==0){ int a=mt()%cover_size,b=mt()%cover_size,c=mt()%cover_size; if(a==b||b==c||a==c) continue; swap(min_cost_cover_v[a],min_cost_cover_v[b]); swap(min_cost_cover_v[b],min_cost_cover_v[c]); int new_cost=fake_cost(min_cost_cover_v,shop_explosion); if(new_cost<=min_cost){ min_cost=new_cost; }else{ swap(min_cost_cover_v[b],min_cost_cover_v[c]); swap(min_cost_cover_v[a],min_cost_cover_v[b]); } }else{ int a=mt()%cover_size,b=mt()%cover_size; if(a==b) continue; swap(min_cost_cover_v[a],min_cost_cover_v[b]); int new_cost=fake_cost(min_cost_cover_v,shop_explosion); if(new_cost<=min_cost) min_cost=new_cost; else swap(min_cost_cover_v[a],min_cost_cover_v[b]); } } vector ans=cover_to_ans(min_cost_cover_v); output_answer(ans); } }Solver; int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); cin >> N >> M; A.resize(N); rep(i,N) cin >> A[i]; bomb.resize(M); rep(i,M){ cin >> bomb[i].C >> bomb[i].L; bomb[i].a.resize(bomb[i].L); bomb[i].b.resize(bomb[i].L); rep(j,bomb[i].L) cin >> bomb[i].a[j] >> bomb[i].b[j]; } Solver.solve(); }