#include #include #pragma GCC optimize "O3,omit-frame-pointer,inline" #define ALL(v) (v).begin(), (v).end() #define OVERLOAD4(_1, _2, _3, _4, name, ...) name #define REP1(n) for(int i=0;ivec; //typedef vectorvec; //typedef vector mat; typedef pair P; typedef pair LP; //const int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1}; //const int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1}; const int INF = 1000000000; const ll LINF = 1000000000000000000;//1e18 const ll MOD = 1000000007; const double PI = acos(-1.0); // const double PI = 2 * acos(0); constexpr double EPS = 1e-10; template inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; } template inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; } /* ----------------------- DEBUG FUNCTION ---------------------------- */ #define DUMPOUT cerr #define DEBUG_ 1 void dump_function() { DUMPOUT << ' '; } void dump_function(bool a) { DUMPOUT << a; } void dump_function(int a) { DUMPOUT << a; } void dump_function(long long a) { DUMPOUT << a; } void dump_function(char a) { DUMPOUT << a; } void dump_function(string &a) { DUMPOUT << a; } void dump_function(double a) { DUMPOUT << a; } template void dump_function(const vector &); template void dump_function(const array &); template void dump_function(const pair &p); template void dump_function(const T (&)[size]); template void dump_function(const vector &a) { if(a.empty()) return; dump_function(a[0]); for(auto i = a.begin(); ++i != a.end();) { DUMPOUT << " "; dump_function(*i); } DUMPOUT << endl; } template void dump_function(const deque &a) { if(a.empty()) return; dump_function(a[0]); for(auto i = a.begin(); ++i != a.end();) { DUMPOUT << " "; dump_function(*i); } } template void dump_function(const array &a) { dump_function(a[0]); for(auto i = a.begin(); ++i != a.end();) { DUMPOUT << " "; dump_function(*i); } } template void dump_function(const pair &p) { DUMPOUT << '('; dump_function(p.first); DUMPOUT << ","; dump_function(p.second); DUMPOUT << ')'; } template void dump_function(set &x) { for(auto e : x) dump_function(e), DUMPOUT << " "; DUMPOUT << endl; } template void dump_function(multiset &x) { for(auto e : x) dump_function(e), DUMPOUT << " "; DUMPOUT << endl; } template void dump_function(const T (&a)[size]) { dump_function(a[0]); for(auto i = a; ++i != end(a);) { DUMPOUT << " "; dump_function(*i); } } template void dump_function(const T &a) { DUMPOUT << a; } int dump_out() { DUMPOUT << '\n'; return 0; } template int dump_out(const T &t) { dump_function(t); DUMPOUT << '\n'; return 0; } template int dump_out(const Head &head, const Tail &... tail) { dump_function(head); DUMPOUT << ' '; dump_out(tail...); return 0; } #ifdef DEBUG_ #define dump(x) \ DUMPOUT << #x << ": "; \ dump_function(x); \ DUMPOUT << endl; void dumps() {} template void dumps(const T &t) { dump_function(t); DUMPOUT << " "; } template void dumps(const Head &head, const Tail &... tail) { dump_function(head); DUMPOUT << ' '; dump_out(tail...); } #else #define dump(x) template void dumps(const T &...) {} #endif /* ----------------------- DEBUG FUNCTION ---------------------------- */ constexpr ll CYCLES_PER_SEC = 2800000000; constexpr double TL = 990; double get_ms() { struct timeval t; gettimeofday(&t, NULL); return (double)t.tv_sec * 1000 + (double)t.tv_usec / 1000; } uint32_t XorShift(void) { static uint32_t x = 123456789; static uint32_t y = 362436069; static uint32_t z = 521288629; static uint32_t w = 88675123; uint32_t t; t = x ^ (x << 11); x = y; y = z; z = w; return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); } double Prob(void){ double ret = (double)XorShift() / UINT_MAX; return ret; } struct RNG { unsigned int MT[624]; int index; RNG(int seed = 1) {init(seed);} void init(int seed = 1) {MT[0] = seed; REP(i, 1, 624) MT[i] = (1812433253UL * (MT[i-1] ^ (MT[i-1] >> 30)) + i); index = 0; } void generate() { const unsigned int MULT[] = {0, 2567483615UL}; REP(i, 227) {unsigned int y = (MT[i] & 0x8000000UL) + (MT[i+1] & 0x7FFFFFFFUL); MT[i] = MT[i+397] ^ (y >> 1); MT[i] ^= MULT[y&1]; } REP(i, 227, 623) {unsigned int y = (MT[i] & 0x8000000UL) + (MT[i+1] & 0x7FFFFFFFUL); MT[i] = MT[i-227] ^ (y >> 1); MT[i] ^= MULT[y&1]; } unsigned int y = (MT[623] & 0x8000000UL) + (MT[0] & 0x7FFFFFFFUL); MT[623] = MT[623-227] ^ (y >> 1); MT[623] ^= MULT[y&1]; } unsigned int rand() { if (index == 0) generate(); unsigned int y = MT[index]; y ^= y >> 11; y ^= y << 7 & 2636928640UL; y ^= y << 15 & 4022730752UL; y ^= y >> 18; index = index == 623 ? 0 : index + 1; return y;} inline __attribute__ ((always_inline)) int next() {return rand(); } inline __attribute__ ((always_inline)) int next(int x) {return rand() % x; } inline __attribute__ ((always_inline)) int next(int a, int b) {return a + (rand() % (b - a)); } inline __attribute__ ((always_inline)) double next_double() {return (rand() + 0.5) * (1.0 / 4294967296.0); } inline __attribute__ ((always_inline)) double next_double(double a, double b) {return a + next_double() * (b - a); } }; static RNG rng; const int N = 100; const int M = 8; const int alpha = 5; vector a(N), b(N); vector c(M), d(M); vector ans; vector> dist(N, vector(N)); double start = 0.0; vector labels(N); vector clusters(M); // cluster[i]に含まれる点の個数 namespace yukicoder_score_contest2{ void init(){ REP(i,N) ans.emplace_back(i); // calc_dist REP(i,N) REP(j,N) dist[i][j] = alpha * alpha * ((a[i] - a[j]) * (a[i] - a[j]) + (b[i] - b[j]) * (b[i] - b[j])); } void input(){ int _N, _M; cin >> _N >> _M; start = get_ms(); REP(i,N) cin >> a[i] >> b[i]; } void output() { // REP(i,M) cout << c[i] << " " << d[i] << "\n"; int idx1 = 0; int sz = ans.size(); cout << sz+1 << endl; REP(i,sz) if(ans[i] == 0) idx1 = i; REP(i,sz) { if(ans[(idx1+i)%sz] >= N) cout << "2 " << ans[(idx1+i)%sz] - N + 1 << "\n"; else cout << "1 " << ans[(idx1+i)%sz] + 1 << "\n"; } cout << "1 " << ans[idx1] + 1 << endl; } int calc_diff(int i0, int i1) { int j0 = (i0 + N - 1) % N; int j1 = (i1 + 1) % N; const double d_cur = dist[ans[i0]][ans[j0]] + dist[ans[i1]][ans[j1]]; const double d_next = dist[ans[i0]][ans[j1]] + dist[ans[i1]][ans[j0]]; return d_cur - d_next; } void k_means() { REP(i,N) labels[i] = i % M; const int MAX_ITER = 1000; int iter = 0; bool update = true; while(iter < MAX_ITER and update) { update = false; REP(i,M) c[i] = d[i] = clusters[i] = 0; REP(i,N) { int label = labels[i]; c[label] += a[i]; d[label] += b[i]; clusters[label]++; } REP(i,M) if(clusters[i] > 0) c[i] /= clusters[i], d[i] /= clusters[i]; REP(i,N) { int mi = INF; int new_cluster = labels[i]; REP(j,M) if(chmin(mi, (a[i] - c[j]) * (a[i] - c[j]) + (b[i] - b[j]) * (b[i] - b[j]))) new_cluster = j; if(labels[i] != new_cluster) { update = true; labels[i] = new_cluster; } } iter++; } dump(clusters); dump(iter); } void output_k_means() { REP(i,M) cout << c[i] << " " << d[i] << endl; } void SA(){ int iter = 0; int move = 0; int last_move = 0; const double T_init = 180; const double T_end = 10; double T = 100; for(iter = 1 ; ; iter++) { int i0 = rng.next(N); int i1 = rng.next(N); if(i0 > i1) swap(i0, i1); const int diff = calc_diff(i0, i1); if(diff > 0 or exp(diff / T) > (double)rng.next(INF+9)) { reverse(ans.begin() + i0, ans.begin() + i1 + 1); move++; last_move = iter; } if(iter % 1000 == 0) { double elapsed = get_ms() - start; if(elapsed > TL) break; T = (T_end - T_init) / TL * elapsed + T_init; } } dump(iter); dump(move); dump(last_move); } void greedy() { // dump(ans); // REP(i,M) { // int ma = 0; // int idx = -1; // int sz = ans.size(); // int best_mx = -1; // int best_my = -1; // dump(sz); // REP(j,sz) { // int i0 = ans[j]; // int i1 = ans[(j+1)%sz]; // int x_i0 = (i0 >= N ? c[i0 - N] : a[i0]); // int y_i0 = (i0 >= N ? d[i0 - N] : b[i0]); // int x_i1 = (i1 >= N ? c[i1 - N] : a[i1]); // int y_i1 = (i1 >= N ? d[i1 - N] : b[i1]); // int mx = (x_i0 + x_i1) / 2; // int my = (y_i0 + y_i1) / 2; // int d_cur = (x_i0 - x_i1) * (x_i0 - x_i1) + (y_i0 - y_i1) * (y_i0 - y_i1); // if(i0 < N) d_cur *= alpha; // if(i1 < N) d_cur *= alpha; // int d_next = (i0 < N ? alpha : 1) * ((x_i0 - mx) * (x_i0 - mx) + (y_i0 - my) * (y_i0 - my)); // d_next += (i1 < N ? alpha : 1) * ((x_i1 - mx) * (x_i1 - mx) + (y_i1 - my) * (y_i1 - my)); // if(chmax(ma, d_cur - d_next)) { // idx = j; // best_mx = mx; // best_my = my; // } // } // if(idx) { // ans.insert(ans.begin() + idx + 1, i + N); // c[i] = best_mx; // d[i] = best_my; // } // } REP(j,ans.size()) { int i0 = ans[j]; int i1 = ans[(j+1)%(int)ans.size()]; if(i0 >= N or i1 >= N) continue; if(labels[i0] != labels[i1]) continue; int x_i0 = (i0 >= N ? c[i0 - N] : a[i0]); int y_i0 = (i0 >= N ? d[i0 - N] : b[i0]); int x_i1 = (i1 >= N ? c[i1 - N] : a[i1]); int y_i1 = (i1 >= N ? d[i1 - N] : b[i1]); int mx = c[labels[i0]]; int my = d[labels[i0]]; int d_cur = (x_i0 - x_i1) * (x_i0 - x_i1) + (y_i0 - y_i1) * (y_i0 - y_i1); if(i0 < N) d_cur *= alpha; if(i1 < N) d_cur *= alpha; int d_next = (i0 < N ? alpha : 1) * ((x_i0 - mx) * (x_i0 - mx) + (y_i0 - my) * (y_i0 - my)); d_next += (i1 < N ? alpha : 1) * ((x_i1 - mx) * (x_i1 - mx) + (y_i1 - my) * (y_i1 - my)); if(d_cur - d_next > 0) { ans.insert(ans.begin() + j + 1, labels[i0] + N); j++; } } } void main(){ input(); init(); k_means(); output_k_means(); SA(); greedy(); output(); } } int main(){ cin.tie(0); ios::sync_with_stdio(false); yukicoder_score_contest2::main(); }