#if !__INCLUDE_LEVEL__ #include __FILE__ constexpr clock_t TL = 0.95*CLOCKS_PER_SEC; constexpr int alpha = 5; constexpr int N = 100; constexpr int M = 8; using output_t = vector>; using stations_t = array,M>; using pos_t = array, N>; void output(const output_t &ans, const stations_t &stations){ REP(i,M)cout << stations[i].first << " " << stations[i].second << "\n"; cout << ans.size() << "\n"; REP(i,ans.size())cout << ans[i].first << " " << ans[i].second+1 << "\n"; } int calc_energy(const output_t &ans, const stations_t &stations, const array, N> &pos){ int energy = 0; int prev_x = pos[0].first; int prev_y = pos[0].second; bool prev_is_planet = true; REP(i,ans.size()){ if(i==0)continue; int cur_energy = 0; int idx = ans[i].second; if(ans[i].first==1){ cur_energy += (prev_x-pos[idx].first)*(prev_x-pos[idx].first) + (prev_y-pos[idx].second)*(prev_y-pos[idx].second); if(prev_is_planet){ cur_energy *= 5*5; } else{ cur_energy *= 5; } prev_x = pos[idx].first; prev_y = pos[idx].second; prev_is_planet=true; } else{ cur_energy += (prev_x-stations[idx].first)*(prev_x-stations[idx].first) + (prev_y-stations[idx].second)*(prev_y-stations[idx].second); if(prev_is_planet){ cur_energy *= 5; } else{ cur_energy *= 1; } prev_x = stations[idx].first; prev_y = stations[idx].second; prev_is_planet=false; } energy += cur_energy; } return energy; } // calc after swapped int calc_energy_diff(const output_t &ans, const stations_t &stations, const array, N> &pos, const int prev_energy, const int swap_a, const int swap_b){ pair prev_a = ans[swap_a-1].first==1? pos[ans[swap_a-1].second]: stations[ans[swap_a-1].second]; pair curr_a = ans[swap_a-1].first==1? pos[ans[swap_a-1].second]: stations[ans[swap_a-1].second]; pair next_a = ans[swap_a-1].first==1? pos[ans[swap_a-1].second]: stations[ans[swap_a-1].second]; pair prev_b = ans[swap_b-1].first==1? pos[ans[swap_b-1].second]: stations[ans[swap_b-1].second]; pair curr_b = ans[swap_b-1].first==1? pos[ans[swap_b-1].second]: stations[ans[swap_b-1].second]; pair next_b = ans[swap_b-1].first==1? pos[ans[swap_b-1].second]: stations[ans[swap_b-1].second]; int pa2ca = (prev_a.first-curr_a.first)*(prev_a.first-curr_a.first) + (prev_a.second-curr_a.second)*(prev_a.second-curr_a.second); int ca2na = (curr_a.first-next_a.first)*(curr_a.first-next_a.first) + (curr_a.second-next_a.second)*(curr_a.second-next_a.second); int pb2ca = (prev_b.first-curr_a.first)*(prev_b.first-curr_a.first) + (prev_b.second-curr_a.second)*(prev_b.second-curr_a.second); int ca2nb = (curr_a.first-next_b.first)*(curr_a.first-next_b.first) + (curr_a.second-next_b.second)*(curr_a.second-next_b.second); int pb2cb = (prev_b.first-curr_b.first)*(prev_b.first-curr_b.first) + (prev_b.second-curr_b.second)*(prev_b.second-curr_b.second); int cb2nb = (curr_b.first-next_b.first)*(curr_b.first-next_b.first) + (curr_b.second-next_b.second)*(curr_b.second-next_b.second); int pa2cb = (prev_a.first-curr_b.first)*(prev_a.first-curr_b.first) + (prev_a.second-curr_b.second)*(prev_a.second-curr_b.second); int cb2na = (curr_b.first-next_a.first)*(curr_b.first-next_a.first) + (curr_b.second-next_a.second)*(curr_b.second-next_a.second); int diff_a = (pa2ca+ca2na) - (pb2ca+ca2nb); int diff_b = (pb2cb+cb2nb) - (pa2cb+cb2na); return prev_energy - (diff_a + diff_b); } void simple_solution(output_t &ans, const pos_t &pos){ vector seen(N); seen[0]=true; int upper = floor((N-1)/2.0); REP(i,upper){ int least_len = 1e9; int idx = ans[i].second; int best_next_idx = 0; REP(j,N){ if(seen[j])continue; int dist = (pos[j].first-pos[idx].first)*(pos[j].first-pos[idx].first) + (pos[j].second-pos[idx].second)*(pos[j].second-pos[idx].second); if( dist < least_len){ best_next_idx = j; least_len = dist; } } ans[1+i].second = best_next_idx; seen[best_next_idx] = true; } int lower = ceil((N-1)/2.0); REP(i,lower){ int least_len = 1e9; int idx = ans[N-i].second; int best_next_idx = 0; REP(j,N){ if(seen[j])continue; int dist = (pos[j].first-pos[idx].first)*(pos[j].first-pos[idx].first) + (pos[j].second-pos[idx].second)*(pos[j].second-pos[idx].second); if( dist < least_len){ best_next_idx = j; least_len = dist; } } ans[N-i-1].second = best_next_idx; seen[best_next_idx] = true; } } void mauntain(output_t &ans, stations_t &stations, const pos_t &pos, const clock_t TL){ mt19937_64 rng(0); int best_energy = calc_energy(ans, stations, pos); int loop = 0; while(true){ if(loop%75 && clock() > TL){ break; } { int swap_a = rng()%(ans.size()-2) +1; int swap_b = rng()%(ans.size()-2) +1; swap(ans[swap_a], ans[swap_b]); int energy = calc_energy_diff(ans, stations, pos, best_energy, swap_a, swap_b); if(energy < best_energy){ best_energy = energy; } else{ swap(ans[swap_a], ans[swap_b]); } } loop += 1; } #if LOCAL cerr << "loop: " << setw(9) << loop << "\n"; #endif } void add_stations_to_midpoint(output_t &ans, stations_t &stations, const pos_t &pos){ vector,pair>>> lens(ans.size()-1); REP(i,ans.size()-1){ int prev_x = ans[i].first==1? pos[ans[i].second].first: stations[ans[i].second].first; int prev_y = ans[i].first==1? pos[ans[i].second].second: stations[ans[i].second].second; int next_x = ans[i+1].first==1? pos[ans[i+1].second].first: stations[ans[i+1].second].first; int next_y = ans[i+1].first==1? pos[ans[i+1].second].second: stations[ans[i+1].second].second; lens[i].first = (prev_x-next_x)*(prev_x-next_x) + (prev_y-next_y)*(prev_y-next_y); lens[i].second.first = pair((prev_x+next_x)/2, (prev_y+next_y)/2); lens[i].second.second = ans[i]; } sort(ALL(lens), greater,pair>>>()); REP(i,M){ stations[i] = lens[i].second.first; ans.insert(find(ALL(ans), lens[i].second.second)+1, pair(2, i)); } } void solve(pos_t &pos){ output_t ans(N+1, pair(1,0)); REP(i,N)ans[i].second = i; array, M> stations; simple_solution(ans, pos); mauntain(ans, stations, pos, TL/2); add_stations_to_midpoint(ans, stations, pos); mauntain(ans, stations, pos, TL); output(ans, stations); cerr << calc_energy(ans, stations, pos) << "\n"; } signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); ll _N,_M; cin >> _N >> _M; array, N> pos; REP(i,_N)cin >> pos[i].first >> pos[i].second; solve(pos); #if LOCAL cerr << ((double)clock()/CLOCKS_PER_SEC) << "\n"; #endif return 0; } //====================temp==================== #else #include using namespace std; #define REP(i, n) for (int i = 0; i < (int)(n); i++) #define RREP(i, n) for (int i = ((int)(n)-1); i >= 0; i--) #define REPITR(itr, ARRAY) for (auto itr = (ARRAY).begin(); itr != (ARRAY).end(); ++itr) #define RREPITR(itr, ARRAY) for (auto itr = (ARRAY).rbegin(); itr != (ARRAY).end(); ++itr) #define ALL(n) (n).begin(),(n).end() using ll = long long; using ull = unsigned long long; #endif