#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); } 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(); while(true){ if(true){ ms=Timer::get_ms(); if(limit_ms<=ms) break; //double t=(double)ms/limit_ms; temp=start_temp-(start_temp-end_temp)/limit_ms*ms; //temp=pow(start_temp,1-t)*pow(end_temp,t); } loop_cnt++; double accept_diff=log(rand_double())*temp; bool accepted=state.modify(accept_diff); if(accepted){ accept_cnt++; if(best_state.score A,B; array,N*N> G; vector E; int one(int i,int j){ return i*N+j; } pii two(int x){ return {x/N,x%N}; } int calc_income(const vector &edges){ set st(all(edges)); array,N*N> g; rep(i,N*N){ rep(k,4){ if(G[i][k]==-1){ g[i][k]={-1,INF}; }else{ if(st.contains({i,G[i][k]})||st.contains({G[i][k],i})){ g[i][k]={G[i][k],223}; }else{ g[i][k]={G[i][k],1000}; } } } } array,N*N> dist; array,N*N> cnt; rep(i,N*N){ dist[i].fill(INF); cnt[i].fill(0); priority_queue,greater> pq; dist[i][i]=0; pq.push({0,i}); while(!pq.empty()){ auto [d,x]=pq.top(); pq.pop(); if(dist[i][x]!=d) continue; for(auto [y,c]:g[x]){ if(y==-1) continue; if(chmin(dist[i][y],dist[i][x]+c)){ cnt[i][y]=cnt[i][x]+(c==223); pq.push({dist[i][y],y}); } } } } int sum=0; rep(i,K){ sum+=cnt[A[i]][B[i]]; } return 60*sum; } namespace Solver{ array,N*N> start_dist; array,N*N> start_cnt; vector first_edges={{90,91},{89,90},{91,92},{88,89},{92,93},{87,88},{93,94},{86,87},{94,95},{85,86},{95,96},{84,85},{96,110},{110,124},{124,138},{138,152},{152,166},{82,96},{68,82},{54,68},{40,54},{39,40},{38,39},{37,38},{36,37},{165,166},{164,165},{163,164},{162,163},{161,162},{160,161},{159,160},{158,159},{157,158},{156,157},{35,36},{34,35},{33,34},{32,33},{31,32},{30,31},{155,156},{29,30},{154,155},{28,29},{147,161},{133,147},{132,133},{131,132},{130,131},{129,130},{128,129},{127,128},{26,40},{166,180},{180,194},{137,138},{136,137},{122,136},{12,26},{36,50},{50,51},{126,127},{121,122},{49,50},{123,137},{23,37},{9,23},{20,34},{6,20},{5,6},{5,19},{4,5},{3,4},{2,3},{1,2},{18,19},{17,18},{16,17},{15,16},{14,15},{20,21},{163,177},{177,191},{177,178},{160,174},{174,175},{173,174},{158,172},{171,172},{170,171},{169,170},{168,169},{0,1},{23,24},{151,165},{150,151},{39,53},{67,68},{66,67},{52,53},{48,49},{47,48},{46,47},{35,49},{45,46},{44,45},{43,44},{42,43},{67,81},{132,146},{145,146},{80,81},{79,80},{78,79},{77,78},{76,77},{75,76},{74,75},{73,74},{72,73},{71,72},{70,71},{109,110},{179,180},{144,145},{143,144},{142,143},{141,142},{140,141},{22,23},{108,109},{176,177},{25,26},{149,163},{7,21},{8,22},{170,184},{184,185},{183,184},{182,183},{40,41},{41,55},{27,41},{13,27},{68,69},{69,83},{96,97},{97,111},{124,125},{125,139},{152,153},{153,167},{167,181},{181,195},{172,186},{186,187},{174,188},{148,162},{134,148},{107,108},{188,189},{176,190},{64,65},{9,10},{11,25},{191,192},{179,193},{147,148},{159,173}}; struct State{ vector edges; int score=0; State(){ edges=first_edges; score=get_score(); } int get_score(){ int sz=len(edges); vector income; income.push_back(0); auto dist=start_dist; auto cnt=start_cnt; for(auto [u,v]:edges){ rep(i,N*N){ rep(j,N*N){ if(chmin(dist[i][j],dist[i][u]+223+dist[v][j])) cnt[i][j]=cnt[i][u]+1+cnt[v][j]; if(chmin(dist[i][j],dist[i][v]+223+dist[u][j])) cnt[i][j]=cnt[i][v]+1+cnt[u][j]; } } int sum=0; rep(i,K){ sum+=cnt[A[i]][B[i]]; } income.push_back(sum*60); } const int P=100; vector> dp(sz+1,vector(P,{INF,INF})); dp[0][1]={0,-M}; rep(k,sz){ rep(i,P){ auto [turn,money]=dp[k][i]; if(turn==INF) continue; money=-money; replr(j,i,P){ int cost=floor((double)1e7/sqrt(j)); int add_turn=j-i; int income_turn=(max(0,cost-(money+income[k]*add_turn))+(50000+income[k])-1)/(50000+income[k]); int new_turn=turn+add_turn+income_turn+1; int new_money=money; new_money+=income[k]*add_turn; new_money+=(50000+income[k])*income_turn; new_money-=(int)floor((double)1e7/sqrt(j)); assert(0<=new_money); new_money+=income[k+1]; chmin(dp[k+1][j],{new_turn,-new_money}); } } } int best_money=0; rep(i,P){ auto [turn,money]=dp[sz][i]; if(T income; income.push_back(0); auto dist=start_dist; auto cnt=start_cnt; for(auto [u,v]:edges){ rep(i,N*N){ rep(j,N*N){ if(chmin(dist[i][j],dist[i][u]+223+dist[v][j])) cnt[i][j]=cnt[i][u]+1+cnt[v][j]; if(chmin(dist[i][j],dist[i][v]+223+dist[u][j])) cnt[i][j]=cnt[i][v]+1+cnt[u][j]; } } int sum=0; rep(i,K){ sum+=cnt[A[i]][B[i]]; } income.push_back(sum*60); } vector>> dp(T+1,vector>(T+2,vector(sz+1,-INF))); //[turn][協力者数][進行度]=所持金 vector>> pre(T+1,vector>(T+2,vector(sz+1,{-1,-1,-1}))); dp[0][1][0]=M; rep(t,T){ rep(i,T+2){ int cost=floor(1e7/sqrt(i)); rep(k,sz+1){ if(dp[t][i][k]<0) continue; if(k+1<=sz&&cost<=dp[t][i][k]){ if(chmax(dp[t+1][i][k+1],dp[t][i][k]-cost+income[k+1])){ pre[t+1][i][k+1]={t,i,k}; } } if(i+1 ans; vector income_v; while(0<=nt){ auto [pt,pi,pk]=pre[nt][ni][nk]; if(pt==-1) break; if(pk!=nk) ans.emplace_back(1,edges[pk].first,edges[pk].second); else if(pi!=ni) ans.emplace_back(2,-1,-1); else ans.emplace_back(3,-1,-1); nt=pt; ni=pi; nk=pk; income_v.push_back(dp[nt][ni][nk]); } reverse(all(ans)); reverse(all(income_v)); assert(len(ans)==T); int idx=0; for(auto [t,u,v]:ans){ int x,y; cin >> x >> y; #ifndef LOCAL assert(income_v[idx]==x); #endif if(t==1){ auto [a,b]=two(u); auto [c,d]=two(v); cout << "1 " << a+1 << ' ' << b+1 << ' ' << c+1 << ' ' << d+1 << '\n'; cout.flush(); }else{ cout << t << '\n'; cout.flush(); } idx++; } } bool modify(double accept_diff){ auto pre_edges=edges; int r=rand_int(2); if(r==0||edges.empty()){ edges.insert(edges.begin()+rand_int(len(pre_edges)+1),get_random_element(E)); }else if(r==1){ edges.erase(edges.begin()+rand_int(len(pre_edges))); }/*else if(r==2){ swap(edges[rand_int(len(pre_edges))],edges[rand_int(len(pre_edges))]); }else{ edges[rand_int(len(pre_edges))]=get_random_element(E); }*/ int new_score=get_score(); //cerr << score << " " << new_score << endl; if(accept_diff<=new_score-score){ score=new_score; return true; }else{ edges=pre_edges; return false; } } }; void init(){ rep(i,N*N){ start_dist[i].fill(INF); start_cnt[i].fill(0); priority_queue,greater> pq; start_dist[i][i]=0; pq.push({0,i}); while(!pq.empty()){ auto [d,x]=pq.top(); pq.pop(); if(start_dist[i][x]!=d) continue; for(auto y:G[x]){ if(y==-1) continue; if(chmin(start_dist[i][y],start_dist[i][x]+1000)){ pq.push({start_dist[i][y],y}); } } } } /*auto dist=start_dist; auto cnt=start_cnt; rep(_,N*N){ int best_diff=0; int best_u=-1,best_v=-1; for(auto [u,v]:E){ auto now_dist=dist; auto now_cnt=cnt; int diff=0; rep(i,N*N){ rep(j,N*N){ if(chmin(now_dist[i][j],now_dist[i][u]+223+now_dist[v][j])){ diff-=now_cnt[i][j]; now_cnt[i][j]=now_cnt[i][u]+1+now_cnt[v][j]; diff+=now_cnt[i][j]; } if(chmin(now_dist[i][j],now_dist[i][v]+223+now_dist[u][j])){ diff-=now_cnt[i][j]; now_cnt[i][j]=now_cnt[i][v]+1+now_cnt[u][j]; diff+=now_cnt[i][j]; } } } if(chmax(best_diff,diff)){ best_u=u; best_v=v; } } if(best_diff==0) exit(0); int u=best_u,v=best_v; rep(i,N*N){ rep(j,N*N){ if(chmin(dist[i][j],dist[i][u]+223+dist[v][j])){ cnt[i][j]=cnt[i][u]+1+cnt[v][j]; } if(chmin(dist[i][j],dist[i][v]+223+dist[u][j])){ cnt[i][j]=cnt[i][v]+1+cnt[u][j]; } } } first_edges.emplace_back(u,v); cerr << "{" << u << "," << v << "},"; } exit(0);*/ } void solve(){ init(); first_edges.resize(100); State state; state=SA(state); state.output_ans(); } } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); Timer::program_start_snap(); int k,t; cin >> k >> t; assert(k==K); assert(t==T); A.fill(-1); B.fill(-1); rep(i,K){ int a,b,c,d; cin >> a >> b >> c >> d; a--; b--; c--; d--; A[i]=one(a,b); B[i]=one(c,d); } rep(i,N*N) G[i].fill(-1); rep(i,N){ rep(j,N){ if(j+1