#pragma GCC target("prefer-vector-width=512") #pragma GCC target("avx512f,avx512dq,avx512ifma,avx512cd,avx512bw,avx512vl,avx512vbmi,avx512vbmi2,avx512vnni,avx512bitalg,avx512vpopcntdq") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #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; } } //参考:https://ei1333.github.io/library/other/xor-shift.hpp.html namespace Random{ uint64_t x=88172645463325252; constexpr uint32_t mask=numeric_limits::max(); constexpr double k=1.0/(double)(numeric_limits::max()); inline uint64_t xorshift64(){ x^=x<<7; x^=x>>9; return x; } inline uint32_t rand_int(uint32_t r){ //[0,r) assert(r!=0); return (xorshift64()&mask)*r>>32; } inline int rand_int(int l,int r){ //[l,r) assert(l<=r); return l+rand_int(r-l); } inline double rand_double(){ // [0.0,1.0] return xorshift64()*k; } } using Random::rand_int,Random::rand_double; template 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); } template SA_State SA(const SA_State &first_state){ SA_State state=first_state,best_state=state; int loop_cnt=0,accept_cnt=0,update_cnt=0; int ms=0; double temp=start_temp; Timer::snap(); constexpr int b=16,sz=1< log_rd; rep(i,sz) log_rd[i]=log(rand_double()); while(true){ if((loop_cnt&1023)==1023){ ms=Timer::get_ms(); if(limit_ms<=ms) break; temp=start_temp-(start_temp-end_temp)/limit_ms*ms; } loop_cnt++; double accept_diff=log_rd[loop_cnt&(sz-1)]*temp; bool accepted=state.modify(accept_diff); if(accepted){ accept_cnt++; if(state.score P,K; array,N*N> G; int Start,Key,Goal; int one(int i,int j){ return i*N+j; } pii two(int x){ return {x/N,x%N}; } namespace Solver{ array,N*N> grid_damage; pair,vector> dijkstra_cost(int s,int start_turn,bool goal_ng,const vector &gs){ static array,N*N> cost; static array,N*N> turn; static array,N*N> last_vis; static int vis_cnt=0; if(vis_cnt==0){ rep(i,N*N){ cost[i].fill(INF); last_vis[i].fill(-1); } } vis_cnt++; int ts=start_turn%L; cost[s][ts]=0; last_vis[s][ts]=vis_cnt; turn[s][ts]=0; priority_queue,greater> pq; pq.push({0,s,ts}); unordered_set st(all(gs)); unordered_map mp; while(!pq.empty()){ auto [d,x,tx]=pq.top(); pq.pop(); if(cost[x][tx]!=d) continue; if(st.contains(x)){ st.erase(x); mp[x]=tx; if(st.empty()) break; } if(goal_ng&&x==Goal) continue; int ty=(tx+1)%L; for(auto y:G[x]){ if(y==-1) continue; if(last_vis[y][ty]!=vis_cnt||cost[x][tx]+grid_damage[y][ty] ret_cost,ret_turn; for(auto g:gs){ /*if(last_vis[g][mp[g]]!=vis_cnt){ auto [si,sj]=two(s); auto [gi,gj]=two(g); cerr << si << " " << sj << " " << gi << " " << gj << endl; }*/ assert(last_vis[g][mp[g]]==vis_cnt); ret_cost.push_back(cost[g][mp[g]]); ret_turn.push_back(turn[g][mp[g]]); } return {ret_cost,ret_turn}; } vector dijkstra_route(int s,int start_turn,bool goal_ng,int g){ static array,N*N> cost; static array,N*N> turn; static array,N*N> pre; static array,N*N> last_vis; static int vis_cnt=0; if(vis_cnt==0){ rep(i,N*N){ cost[i].fill(INF); pre[i].fill({-1,-1}); last_vis[i].fill(-1); } } vis_cnt++; int ts=start_turn%L; cost[s][ts]=0; last_vis[s][ts]=vis_cnt; turn[s][ts]=0; priority_queue,greater> pq; pq.push({0,s,ts}); int tg=-1; while(!pq.empty()){ auto [d,x,tx]=pq.top(); pq.pop(); if(cost[x][tx]!=d) continue; if(g!=-1&&x==g){ tg=tx; break; } if(goal_ng&&x==Goal) continue; int ty=(tx+1)%L; for(auto y:G[x]){ if(y==-1) continue; if(last_vis[y][ty]!=vis_cnt||cost[x][tx]+grid_damage[y][ty] ret; int x=g,tx=tg; while(!(x==s&&tx==ts)){ ret.push_back(x); auto [y,ty]=pre[x][tx]; assert(y!=-1); assert(ty!=-1); x=y; tx=ty; } reverse(all(ret)); return ret; } array,N*N> two_dist; array,N*N> two_dist_pre; struct SA_State{ vector pos; int sz=0; int score=INF; SA_State(){ pos.push_back(Start); rep(i,N*N){ if((S[i]=='J'||i==Key)&&two_dist[Start][i]!=INF) pos.push_back(i); } pos.push_back(Goal); sz=len(pos); score=calc_score(); } int calc_score() const{ int ret=0; rep(i,sz-1){ ret+=two_dist[pos[i]][pos[i+1]]; } return ret; } bool modify(double accept_diff){ int l=rand_int(1,sz-1),r=rand_int(1,sz-1); if(l==r) return false; if(r ans){ int x=Start; for(auto p:ans){ int t=-1; rep(k,5){ if(G[x][k]==p) t=k; } assert(t!=-1); if(t==4) cout << "S\n"; else cout << "M " << UDLR[t] << '\n'; x=p; } } void solve(){ rep(i,N*N) grid_damage[i].fill(1); rep(m,M){ rep(k,4){ int p=P[m]; while(p!=-1){ p=G[p][k]; if(p!=-1){ for(int t=0;t q; q.push(s); while(!q.empty()){ int x=q.front(); q.pop(); if(x==Goal) continue; //Goalを閉じて途中で終了しないようにごまかしている for(auto y:G[x]){ if(y==-1) continue; if(chmin(two_dist[s][y],two_dist[s][x]+1)){ two_dist_pre[s][y]=x; q.push(y); } } } } SA_State sa_state; sa_state=SA(sa_state); vector pos=sa_state.pos; int sz=len(pos); vector> dp(sz,vector(sz+1,{INF,INF})); //[pos_index][cnt]={damage,turn} vector> pre(sz,vector(sz+1,{-1,-1})); dp[0][0]={0,0}; bool have_key=false; constexpr int W=8; int key_idx=-1; rep(i,sz){ if(pos[i]==Key) key_idx=i; } assert(key_idx!=-1); rep(i,sz-1){ if(pos[i]==Key) have_key=true; //cerr << i << " " << sz << " " << Timer::get_ms_all_program() << endl; vector gs; replr(j,i+1,min({sz,i+W,i in_turn; in_turn.fill(false); rep(c,sz){ auto [damage,turn]=dp[i][c]; if(H,L> turn_diff_damages; array,L> turn_diff_turns; rep(l,L){ if(!in_turn[l]) continue; auto [diff_damages,diff_turns]=dijkstra_cost(pos[i],l,have_key,gs); turn_diff_damages[l]=diff_damages; turn_diff_turns[l]=diff_turns; } rep(c,sz){ auto [damage,turn]=dp[i][c]; if(H dp_route; while(!(xi==0&&xc==0)){ dp_route.push_back(xi); auto [pi,pc]=pre[xi][xc]; xi=pi; xc=pc; } reverse(all(dp_route)); vector ans; int pos_idx=0; have_key=false; for(auto e_idx:dp_route){ if(pos[e_idx]==Key) have_key=true; vector now=dijkstra_route(pos[pos_idx],len(ans),have_key,pos[e_idx]); pos_idx=e_idx; add(ans,now); } output_ans(ans); } } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); Timer::program_start_snap(); int n,h; cin >> n >> D >> h; rep(i,N){ string s; cin >> s; S+=s; } cin >> M; P.resize(M); K.resize(M); rep(i,M){ int y,x; cin >> y >> x >> K[i]; P[i]=one(y,x); } vector pi={-1,1,0,0,0},pj={0,0,-1,1,0}; rep(i,N){ rep(j,N){ G[one(i,j)].fill(-1); //if(S[one(i,j)]=='#'||S[one(i,j)]=='E') continue; rep(k,5){ int ti=i+pi[k],tj=j+pj[k]; if(ti<0||N<=ti||tj<0||N<=tj) continue; if(S[one(ti,tj)]=='#'||S[one(ti,tj)]=='E') continue; G[one(i,j)][k]=one(ti,tj); } } } rep(i,N*N){ if(S[i]=='S') Start=i; if(S[i]=='K') Key=i; if(S[i]=='G') Goal=i; } Solver::solve(); exit(0); }