#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; struct State{ vector edges; int score=0; State(){ rep(i,N-1) edges.emplace_back(one(N/2,i),one(N/2,i+1)); rep(i,N-1) edges.emplace_back(one(i,N/2),one(i+1,N/2)); 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); } int turn=0,money=M,people=1; rep(k,sz){ //cerr << turn << " : " << money << " " << people << endl; int best_turn=INF,add_people=0; replr(p,people,T+2){ int now_add_people=p-people; int cost=floor((double)1e7/sqrt(p)); int need_turn=now_add_people+(max(0,cost-money+income[k]*now_add_people)+(50000+income[k])-1)/(50000+income[k])+1; if(chmin(best_turn,need_turn)){ add_people=now_add_people; } } if(T<=turn+best_turn) return 0; turn+=best_turn; money+=income[k]*add_people; people+=add_people; money+=(50000+income[k])*(best_turn-1-add_people); money-=(int)floor((double)1e7/sqrt(people)); assert(0<=money); money+=income[k+1]; } money+=(T-turn)*(50000+income[sz]); //cerr << money << endl; return money; } void output_ans(){ 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); } 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; //assert(income_v[idx]==x); 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(3); 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}); } } } } } void solve(){ init(); 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