#pragma region MACRO #pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include using namespace std; using ll = long long; using ull = unsigned long long; using ld = long double; using vl = vector; template using vc = vector; template using vvc = vector>; #define eb emplace_back #define all(x) (x).begin(), (x).end() #define rep(i, n) for (ll i = 0; i < (n); i++) #define repr(i, n) for (ll i = (n)-1; i >= 0; i--) #define repe(i, l, r) for (ll i = (l); i < (r); i++) #define reper(i, l, r) for (ll i = (r)-1; i >= (l); i--) #define repa(i, n) for (auto &i : n) template inline bool chmax(T1 &a, const T2 &b) { if (a < b) { a = b; return 1; } return 0; } template inline bool chmin(T1 &a, const T2 &b) { if (b < a) { a = b; return 1; } return 0; } struct init { init() { cin.tie(0); ios::sync_with_stdio(false); cout << fixed << setprecision(15); cerr << fixed << setprecision(15); } } init_; template ostream &operator<<(ostream &out, const pair &a) { return out << a.first << ' ' << a.second; } template ostream &operator<<(ostream &out, const vector &a) { for (auto it = a.begin(); it != a.end();) { out << *it; if (++it != a.end()) out << ' '; } return out; } template ostream &operator<<(ostream &out, const array &a) { for (auto it = a.begin(); it != a.end();) { out << *it; if (++it != a.end()) out << ' '; } return out; } template ostream &operator<<(ostream &out, const set &a) { for (auto it = a.begin(); it != a.end();) { out << *it; if (++it != a.end()) out << ' '; } return out; } template ostream &operator<<(ostream &out, const map &a) { for (auto it = a.begin(); it != a.end();) { out << *it; if (++it != a.end()) out << '\n'; } return out; } #ifdef DEBUG template void verr(const vector &a, const N &n) { rep(i, n) cerr << a[i] << " "; cerr << endl; } template void verr(const array &a, const N &n) { rep(i, n) cerr << a[i] << " "; cerr << endl; } ll dbgt = 1; void err() { cerr << "passed " << dbgt++ << endl; } template void err(H &&h, T &&...t) { cerr << h << (sizeof...(t) ? " " : "\n") << flush; if (sizeof...(t) > 0) err(forward(t)...); } #else void err() {} template void err(H &&h, T &&...t) {} template void verr(H &&h, T &&...t) {} #endif const ll INF = 4e18; const ld EPS = 1e-11; const ld PI = acos(-1.0L); // const ll MOD = 1e9 + 7; const ll MOD = 998244353; //--------------------------------------------------------------------------------// inline uint32_t pcg32() { static uint64_t x = 0x0123456789012345u; unsigned count = (unsigned)(x >> 61); x *= 3; x ^= x >> 22; return (uint32_t)(x >> (22 + count)); } #pragma endregion // 時間を出力 chrono::system_clock::time_point startTime, endTime; // 経過時間(ms) を取得 int get_diff_time() { return chrono::duration_cast(chrono::system_clock::now() - startTime).count(); } // [0, a)の整数乱数 inline int get_randint(int a) { return pcg32() % a; } // [0, 1]の乱数 inline double get_randdouble() { return pcg32() / (double)numeric_limits::max(); } // 固定パラメータ constexpr int N = 100; constexpr int M = 8; constexpr int ALPHA = 5; // ハイパーパラメータ --------------------------------- int ZERO = 0; double TIME_LIMIT = 950; // ms enum hyper_param_idx { ZERO_ID, }; struct Solver { struct point { int x, y, id; bool is_planet; point() {} point(int x, int y, int id, bool isplanet): x(x),y(y),id(id),is_planet(isplanet){} int get_distance(point p) const{ int d = (x - p.x) * (x - p.x) + (y - p.y) * (y - p.y); if (p.is_planet and is_planet) { return ALPHA * ALPHA * d; }else if(p.is_planet or is_planet) { return ALPHA * d; }else{ return d; } } int get_raw_distance(point p) { int d = (x - p.x) * (x - p.x) + (y - p.y) * (y - p.y); return d; } }; array ps; array ss; array labels; array, M> lps; vc ans; Solver() { } void kmeans(){ const int iter = 2000; rep(i, N) labels[i] = i % M; auto prelabels = labels; int counter = 0; array pcounts; array psums; while (counter < iter) { rep(i, M) { pcounts[i] = 0; psums[i].x = psums[i].y = 0; } rep(i, N) { int l = labels[i]; pcounts[l]++; psums[l].x += ps[i].x, psums[l].y += ps[i].y; } rep(i, M) { if(pcounts[i] > 0) { ss[i].x = psums[i].x / pcounts[i]; ss[i].y = psums[i].y / pcounts[i]; } } rep(i, N) { int mind = 1e9; rep(j, M) { if(chmin(mind, ps[i].get_raw_distance(ss[j]))) { labels[i] = j; } } } if (labels == prelabels) break; prelabels = labels; } rep(i, N) lps[labels[i]].eb(i); } // 先頭惑星から初めて宇宙ステーションを含む焼きなまし vc sim(int li) { const auto &ls = lps[li]; const auto rp = ss[li]; vc route; if (ls.size() == 0) return route; route.eb(ps[ls[0]]), route.eb(ps[ls[0]]); for(auto pi: ls) { if (pi == ls[0]) continue; const auto &p = ps[pi]; int mind = 1e9, mini = -1, mintype = -1; rep(i, route.size() - 1) { int rd = p.get_distance(rp); int pred = route[i].get_distance(route[i + 1]); int sumd = 0; sumd = p.get_distance(route[i]) + p.get_distance(route[i + 1]); sumd -= pred; if (chmin(mind, sumd)) mini = i + 1, mintype = 0; if(route[i].is_planet) { sumd = rp.get_distance(route[i]) + rd + p.get_distance(route[i + 1]); sumd -= pred; if (chmin(mind, sumd)) mini = i + 1, mintype = 1; } if(route[i + 1].is_planet) { sumd = p.get_distance(route[i]) + rd + rp.get_distance(route[i + 1]); sumd -= pred; if (chmin(mind, sumd)) mini = i + 1, mintype = 2; } if(route[i].is_planet and route[i].is_planet) { sumd = rp.get_distance(route[i]) + 2 * rd + rp.get_distance(route[i + 1]); sumd -= pred; if (chmin(mind, sumd)) mini = i + 1, mintype = 3; } } assert(mini != -1 and mintype != -1); vc ins; if (mintype & 1) ins.eb(rp); ins.eb(p); if (mintype & 2) ins.eb(rp); route.insert(route.begin() + mini, ins.begin(), ins.end()); } return route; } void sa(){ int diff_time = get_diff_time(); kmeans(); // while (diff_time < TIME_LIMIT) { // diff_time = get_diff_time(); // repr(i, N) { // } // } int rtst = labels[0]; array sts; rep(i, M - 1) { sts[i] = (i >= rtst ? i + 1 : i); } // err("rtst", rtst); // err(sts); array, M> routes; rep(i, M) { routes[i] = sim(i); } int mind = 1e9; do { vc res; // res.eb(ps[0]), res.eb(ss[rtst]); // for(auto pi: lps[rtst]) { // if (pi == 0) continue; // res.eb(ps[pi]), res.eb(ss[rtst]); // } // rep(i, M - 1) { // int si = sts[i]; // res.eb(ss[si]); // for(auto pi: lps[si]) { // res.eb(ps[pi]), res.eb(ss[si]); // } // } // res.eb(ss[rtst]), res.eb(ps[0]); res.insert(res.end(), routes[rtst].begin(), routes[rtst].end()); res.eb(ss[rtst]); rep(i, M - 1) { int si = sts[i]; res.eb(ss[si]); res.insert(res.end(), routes[si].begin(), routes[si].end()); res.eb(ss[si]); } res.eb(ss[rtst]), res.eb(ps[0]); int sumd = 0; rep(i, res.size() - 1) { sumd += res[i].get_distance(res[i + 1]); } if(chmin(mind, sumd)) { ans = res; } } while (next_permutation(all(sts))); } void solve() { input(); init(); sa(); output(); } void input() { int n, m; cin >> n >> m; rep(i, N) { cin >> ps[i].x >> ps[i].y; ps[i].id = i; ps[i].is_planet = true; } rep(i, M) { ss[i] = {0, 0, i, false}; } } void init(){ } void output() { rep(i, M) { cout << ss[i].x << " " << ss[i].y << '\n'; } // int n = 101; // cout << n << '\n'; // rep(i, N) cout << 1 << " " << i + 1 << '\n'; // cout << 1 << " " << 1 << '\n'; cout << ans.size() << '\n'; for (auto p : ans) { cout << (p.is_planet ? 1 : 2) << " " << p.id + 1 << '\n'; } } }; int main() { startTime = chrono::system_clock::now(); #ifdef TUNE // params #endif Solver solver; solver.solve(); }