#include #ifdef LOCAL #include #define debug(...) debug_print::multi_print(#__VA_ARGS__, __VA_ARGS__) #else #define debug(...) (static_cast(0)) #endif using namespace std; using ll=long long; // Start 2023.04.23 21:00 // End // Time min // MTK005 constexpr ll TYPE_PLANET = 1; constexpr ll TYPE_STATION = 2; constexpr ll ALPHA = 5; constexpr ll INF = (1LL << 60); ll START_TIME = 0; struct Pos { int x,y; ll type; Pos(int x, int y, ll type) : x(x), y(y), type(type) {} }; std::ostream& operator<<(std::ostream& os, const Pos& pos) { std::ostringstream oss; oss << "(" << pos.x << ", " << pos.y << "), " << pos.type << ""; os << oss.str(); return os; } struct Solver { int N = 0; int M = 0; vector points; Solver(int n, int m, vector& points) : N(n),M(m),points(points) {} void test() { debug(N,M,points); } void solve() { // 貪欲法 set_station(); // debug(points); // 全点間エネルギーを計算 vector> distances(N+M,vector(N+M)); for(int i=0; i visited(N+M,0); vector route; visited[0]++; route.push_back(0); int v = 0; for(int i=0; i 0) continue; // int d = calc_energy(v,next); int d = distances[v][next]; if(d < nearest_dist) { nearest_dist = d; nearest_v = next; } // debug(d); } // 次の頂点に移動 // dijkstraで経路を復元 vector path = djikstra(v,nearest_v); for(auto p : path) { route.push_back(p); } v = nearest_v; visited[v]++; // route.push_back(nearest_v); } // 最後に惑星1に戻る route.push_back(0); // debug(visited); debug(route); double current_score = calc_score(route); int ti = clock(); int TIMELIMIT = 0.95 * CLOCKS_PER_SEC; int cnt = 0; while(clock() - ti < TIMELIMIT) { cnt++; int l = RandInt(1,route.size()-2); int r = RandInt(1,route.size()-2); while(l == r) { l = RandInt(1,route.size()-2); r = RandInt(1,route.size()-2); } if(l > r) swap(l,r); if(calc_energy(route[l],route[r]) + calc_energy(route[l+1],route[r+1]) < calc_energy(route[l],route[l+1]) + calc_energy(route[l],route[r+1])) { for(int k=0; k<(r-l)/2; k++) { swap(route[l+1+k],route[r-k]); } } double new_score = calc_score(route); if(current_score > new_score) { // 元に戻す for(int k=0; k<(r-l)/2; k++) { swap(route[l+1+k],route[r-k]); } } else { current_score = new_score; } } // ここから2-opt // TwoOpt(route,distances); debug(route); debug(cnt); output(route); calc_score(route); } void output(vector& route) { // 宇宙ステーションの座標 for(int i=N; i> v; v.push_back({300,300}); v.push_back({300,500}); v.push_back({300,700}); v.push_back({500,300}); v.push_back({500,700}); v.push_back({700,300}); v.push_back({700,500}); v.push_back({700,700}); for(int i=0; i& route, vector>& distances) { debug(route.size()); for(int i=1; i& route) { ll s = 0; for(int i=0; i djikstra(int i, int j) { // 二点間の最短距離 // vector> dij(N+M); // 経路復元用 1つ前にいた頂点を保存 vector prev_points(N+M,-1); // int k = 0; // for(int k=0; k cur(N+M,INF); vector kakutei(N+M+1,false); priority_queue, vector>, greater>> Q; int start = i; cur[start] = 0; Q.push(make_pair(cur[start],start)); while(!Q.empty()) { auto[d, pos] = Q.top(); Q.pop(); if(kakutei[pos] == true) continue; kakutei[pos] = true; for(int next=0; next cur[pos]+cost) { // 1つ前の点を保存 prev_points[next] = pos; // 値を更新 cur[next] = cur[pos]+cost; Q.push(make_pair(cur[next],next)); } } } // dij[i] = cur; // } // debug(dij); // debug(cur); // debug(prev_points); // 経路復元 // ゴールからたどっていく int v = j; vector path; while(v != i) { path.push_back(v); v = prev_points[v]; } reverse(path.begin(),path.end()); return path; } }; int main() { START_TIME = clock(); int n,m; cin >> n >> m; // vector a(n),b(n); vector points; for(int i=0; i> a >> b; points.emplace_back(Pos(a,b,TYPE_PLANET)); } debug(n,m,points); Solver solver(n,m,points); solver.solve(); return 0; }