#include "iostream" #include "climits" #include "list" #include "queue" #include "stack" #include "set" #include "functional" #include "algorithm" #include "string" #include "map" #include "unordered_map" #include "unordered_set" #include "iomanip" #include "cmath" #include "random" #include "bitset" #include "cstdio" #include "numeric" #include "cassert" #include "ctime" using namespace std; constexpr int by = 5; int N, M; vectorx; vectory; vectorans; class XorShift { unsigned int x, y, z, w, t; public: XorShift() { x = 133553533; y = 314867339; z = 664298413; w = 999999937; t = 0; } unsigned int rand() { t = x ^ (x << 11); x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); return w & 0x7fffffff; } }; XorShift xs; void Initialize() { cin >> N >> M; x.resize(N); y.resize(N); for (int i = 0; i < N; i++) { cin >> x[i] >> y[i]; } } int Score(vector>dis, vectorroute) { int sum = 0; for (int i = 1; i < route.size(); i++) { sum += dis[route[i - 1]][route[i]]; } return round(1e9 / (1000 + sqrt(sum))); } int Dist(int x1, int x2, int y1, int y2) { return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); } void Station() { vectorcl(N); for (int i = 0; i < N; i++) { cl[i] = xs.rand() % M; } vectorcx(M); vectorcy(M); for (int i = 0; i < 100; i++) { for (auto& i : cx)i = 0; for (auto& i : cy)i = 0; vectorcnum(M); for (int i = 0; i < N; i++) { cx[cl[i]] += x[i]; cy[cl[i]] += y[i]; cnum[cl[i]]++; } for (int i = 0; i < M; i++) { if (cnum[i]) { cx[i] /= cnum[i]; cy[i] /= cnum[i]; } } for (int j = 0; j < N; j++) { for (int k = 0; k < M; k++) { if (Dist(x[j], cx[cl[j]], y[j], cy[cl[j]]) > Dist(x[j], cx[k], y[j], cy[k])) { cl[j] = k; } } } } for (int i = 0; i < M; i++) { x.push_back(round(cx[i])); y.push_back(round(cy[i])); } } int bestscore = 0; vectoroutx; vectorouty; void TSP() { vector>dis(N, vector(N)); vector>>use(N, vector>(N)); for (int i = 0; i < N; i++) { for (int j = i + 1; j < N; j++) { dis[j][i] = dis[i][j] = Dist(x[i], x[j], y[i], y[j]) * by * by; for (int k = 0; k < M; k++) { for (int l = 0; l < M; l++) { int c = Dist(x[i], x[N + k], y[i], y[N + k]) * by + Dist(x[N + k], x[N + l], y[N + k], y[N + l]) + Dist(x[N + l], x[j], y[N + l], y[j]) * by; if (c < dis[i][j]) { dis[i][j] = c; use[i][j] = { N + k,N + l }; use[j][i] = { N + l,N + k }; dis[j][i] = c; } } } } } vectorroute(N + 1); for (int i = 0; i < N + 1; i++) { route[i] = i % N; } double startTemp = 10000; double endTemp = 1; for (int loop = 0; loop < 50000; loop++) { int a = xs.rand() % (N - 1); int b = xs.rand() % (N - 2) + a + 1; b %= N - 1; if (a > b)swap(a, b); a++; b += 2; int bef = dis[route[a - 1]][route[a]] + dis[route[b - 1]][route[b]]; int aft = dis[route[a - 1]][route[b - 1]] + dis[route[a]][route[b]]; int dif = bef - aft; double temp = startTemp + (endTemp - startTemp) * loop / 50000; double probability = exp((bef - aft) / temp); bool FORCE_NEXT = probability > ((double)(xs.rand() % 10000000) / 10000000); if (FORCE_NEXT) { reverse(route.begin() + a, route.begin() + b); } else { } } int score = Score(dis, route); cerr << score << endl; if (bestscore < score) { bestscore = score; ans.clear(); outx.clear(); outy.clear(); for (int i = N; i < x.size(); i++) { outx.push_back(x[i]); outy.push_back(y[i]); } ans.push_back(route[0]); for (int i = 0; i < N; i++) { if (use[route[i]][route[i + 1]].size()) { ans.push_back(use[route[i]][route[i + 1]][0]); ans.push_back(use[route[i]][route[i + 1]][1]); } ans.push_back(route[i + 1]); } } } void Output() { cerr << "----------------" << endl; for (int i = 0; i < outx.size(); i++) { cout << outx[i] << " " << outy[i] << endl; } cout << ans.size() << endl; for (auto i : ans) { if (i < N) { cout << 1 << " " << i + 1 << endl; } else { cout << 2 << " " << i - N + 1 << endl; } } } int main() { ios::sync_with_stdio(false); cin.tie(0); Initialize(); for (int i = 0; i < 300; i++) { Station(); TSP(); x.resize(N); y.resize(N); } Output(); }