#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using vec_int = vector; using P = pair; using T = tuple; using ll = long long; // using PQ = priority_queue, vector>, greater>>; #define rep(i, n) for (int i = 0; i < (int)(n); i++) float initial_T_STATION = 5000; float final_T_STATION = 100; float initial_T = 500; float final_T = 100; float TIME_LIMIT = 1000; float TIME_LIMIT_STATION = 1000; float TIME_LIMIT_TSP = 30; float TIME_LIMIT_TSP2 = 600; int RAND_ARR_LEN = 100000; int RAND_RANGE = 1000000000; vector

DIRS = {make_pair(0, -1), make_pair(-1, 0), make_pair(0, 1), make_pair(1, 0)}; bool is_in(int x, int y, int N) { if (x >= 0 && x < N && y >= 0 && y < N) return true; return false; } // std::mt19937 mt{ std::random_device{}() }; std::mt19937 mt{12345}; std::uniform_int_distribution dist(1, RAND_RANGE); float get_time(bool init) { static std::chrono::system_clock::time_point start; if (init) { start = std::chrono::system_clock::now(); } std::chrono::system_clock::time_point end = std::chrono::system_clock::now(); return std::chrono::duration_cast(end - start).count(); //処理に要した時間をミリ秒に変換 } class Rand { private: int count = 0; vec_int rand_arr; public: Rand(){ rep(i, RAND_ARR_LEN){ rand_arr.push_back(dist(mt)); } } ; int get(); int get_rand(int from, int to); float get_float(); } ; int Rand::get() { int num = rand_arr.at(count); count += 1; count %= RAND_ARR_LEN; return num; } int Rand::get_rand(int from, int to) { int diff = to - from; int num = get() % diff; return num + from; } float Rand::get_float() { // 0~1の間の一様乱数 return (float)get() / (float)RAND_RANGE; } Rand ro; float current_tmp_station(float current_time) { return final_T_STATION + (initial_T_STATION - final_T_STATION) * (TIME_LIMIT_STATION - current_time) / TIME_LIMIT_STATION; } bool is_valid_transition_station(int diff, float current_time) { float t = current_tmp_station(current_time); float rand = ro.get_float(); // cerr<<"tmperature"< &stations, vec_int &excluded){ int result = 0; rep(i, N){ if(excluded.at(i)==1)continue; int tmp_dist = INT_MAX; rep(j, M){ tmp_dist = min(tmp_dist, stations.at(j).square_distance(a.at(i), b.at(i))); } result += tmp_dist; } return result; } int sq_dist_between_cities(int i, int j){ int result = 0; result += (a.at(i)-a.at(j))*(a.at(i)-a.at(j)); result += (b.at(i)-b.at(j))*(b.at(i)-b.at(j)); return result; } vector>>> make_dist_map(){ vector>>> result(N, vector>>(N)); vector> visited(N, vec_int(N, 0)); for(int i=0;i, greater> pq; pq.emplace(0, i, -1); while(!pq.empty()){ int dist, pos, prev; tie(dist, pos, prev) = pq.top(); pq.pop(); if(visited.at(i).at(pos)==1)continue; // 都市にたどり着いた時 visited.at(i).at(pos) = 1; visited.at(pos).at(i) = 1; vector

route; if(prev!=-1){ route = result.at(i).at(prev).second; } route.push_back(make_pair(1, pos)); result.at(i).at(pos) = make_pair(dist, route); vector

route2 = route; reverse(route2.begin(), route2.end()); result.at(pos).at(i) = make_pair(dist, route2); for(int j=0;j &stations, vector

&tmp_ans){ int result = 0; for(int i=1;i &stations, vec_int &keiyu_flag, vec_int &routes, vector>>> &dist_map){ int result = 0; rep(i, N){ int prev = routes.at(i); int current = routes.at(i+1); int original_distance = dist_map.at(prev).at(current).first; int after_distance = INT_MAX; int keiyu = -1; rep(j, M){ int dist = 0; dist += stations.at(j).square_distance(a.at(prev), b.at(prev))*5; dist += stations.at(j).square_distance(a.at(current), b.at(current))*5; if(after_distance>dist){ after_distance = dist; keiyu = j; } } if(after_distance &ans, vector &stations, vector>>> &dist_mat){ // 訪れていない場所の中で一番コストが小さくいけそうなところにいく int result = 0; int pos = 0; ans.push_back(make_pair(1, 0)); vec_int visited(N, 0); while(true){ visited.at(pos) = 1; int min_dist = INT_MAX; int next_pos = -1; for(int i=0;itmp_dist){ min_dist = tmp_dist; next_pos = i; } } if(next_pos==-1)break; int tmp_dist2 = calc_dist(stations, ans); for(auto p_pos: dist_mat.at(pos).at(next_pos).second){ // if(p_pos.second == pos&&p_pos.first==1)continue; if(ans.at(ans.size()-1)==p_pos)continue; ans.push_back(p_pos); } int tmp_dist3 = calc_dist(stations, ans); pos = next_pos; result += min_dist; } for(auto p_pos: dist_mat.at(pos).at(0).second){ ans.push_back(p_pos); } result += dist_mat.at(pos).at(0).first; return result; } void adjust_station_pos(vector &stations, vector

&tmp_ans){ vector station_connections(M); rep(i, tmp_ans.size()){ if(tmp_ans.at(i).first==2){ int st = tmp_ans.at(i).second; if(tmp_ans.at(i-1).first==1){ station_connections.at(st).push_back(tmp_ans.at(i-1).second); } if(tmp_ans.at(i+1).first==1){ station_connections.at(st).push_back(tmp_ans.at(i+1).second); } } } for(int station = 0;station find_initial_route(vector>>> &dist_map){ int pos = 0; vec_int visited(N, 0); vec_int result; while(true){ result.push_back(pos); visited.at(pos) = 1; int min_dist = INT_MAX; int min_pos = -1; for(int i=0;idist_map.at(pos).at(i).first){ min_dist = dist_map.at(pos).at(i).first; min_pos = i; } } if(min_pos==-1)break; pos=min_pos; } result.push_back(0); return result; } void cout_ans(vector &route, vector>>> &dist_map, vec_int &keiyu_flag){ vector

result; for(int i=1;i>>> &dist_map){ float start_time = get_time(false); int current_length = 0; rep(i, N){ current_length += dist_map.at(route.at(i)).at(route.at(i+1)).first; } while(true){ float ct = get_time(false)-start_time; if(ct>TIME_LIMIT_TSP)break; int ind1 = ro.get_rand(0, N); int ind2 = ro.get_rand(0, N); if(ind1==ind2)continue; int length1 = dist_map.at(route.at(ind1)).at(route.at(ind1+1)).first; int length2 = dist_map.at(route.at(ind2)).at(route.at(ind2+1)).first; int length1_2 = dist_map.at(route.at(ind1)).at(route.at(ind2)).first; int length2_2 = dist_map.at(route.at(ind1+1)).at(route.at(ind2+1)).first; int diff = length1_2 + length2_2 - length1-length2; if(is_valid_transition_tsp(-1*diff, ct)){ vec_int route2 = route; for(int i=ind1+1; i<=ind2;i++){ route.at(i) = route2.at(ind2-(i-(ind1+1))); } } } return; } void tsp2(vec_int &route, vector>>> &dist_map, vec_int &keiyu_flag, vector &stations){ float start_time = get_time(false); // int current_length = check_keiyu int current_length = check_keiyu(stations, keiyu_flag, route, dist_map); while(true){ float ct = get_time(false)-start_time; if(ct>TIME_LIMIT_TSP)break; int ind1 = ro.get_rand(0, N); int ind2 = ro.get_rand(0, N); if(ind1==ind2)continue; int length1 = dist_map.at(route.at(ind1)).at(route.at(ind1+1)).first; int length2 = dist_map.at(route.at(ind2)).at(route.at(ind2+1)).first; int length1_2 = dist_map.at(route.at(ind1)).at(route.at(ind2)).first; int length2_2 = dist_map.at(route.at(ind1+1)).at(route.at(ind2+1)).first; int diff = length1_2 + length2_2 - length1-length2; if(is_valid_transition_tsp2(-1*diff, ct)){ vec_int route2 = route; for(int i=ind1+1; i<=ind2;i++){ route.at(i) = route2.at(ind2-(i-(ind1+1))); } } } return; } vec_int annealing(vec_int &route, vector &stations, vector>>> &dist_map){ vec_int distance(N); vec_int keiyu(N, -1); for(int i=0;itmp){ after_dist = tmp; keiyu_station = j; } } if(after_dist>original_distance){ distance.at(i) = original_distance; }else{ distance.at(i) = after_dist; keiyu.at(i) = keiyu_station; } } int tot_distance = 0; rep(i, N)tot_distance += distance.at(i); int count = 0; while(true){ // cerr<<"count:"<=TIME_LIMIT*0.98)break; if(count<0){ // 2-opt int a = ro.get_rand(0, N); int b = ro.get_rand(0, N); if(abs(a-b)<=1)continue; int city1 = min(a, b); int city2 = max(a, b); // cerr<tmp1){ after1 = tmp1; keiyu1 = j; } } int after2 = dist_map.at(route.at(city1+1)).at(route.at(city2+1)).first; int keiyu2 = -1; for(int j=0;jtmp2){ after2 = tmp2; keiyu2 = j; } } int diff = (original_distance-(after1+after2)); if(is_valid_transition_tsp(diff, ct)){ // cerr<<"valid"<tmp){ diff += tmp-dist1; } } } if(is_valid_transition_station(-1*diff, ct)){ // cerr<<"diff:"<<-1*diff<tmp){ distance.at(i) = tmp; keiyu.at(i) = index; } tot_distance -= dist1; tot_distance += distance.at(i); } } }else{ stations.at(index).x = original_x; stations.at(index).y = original_y; } } count++; if(count==300)count=0; } /* for(int i=0;itmp){ after_dist = tmp; keiyu_station = j; } } if(after_dist>original_distance){ distance.at(i) = original_distance; }else{ distance.at(i) = after_dist; keiyu.at(i) = keiyu_station; } } */ cerr<<"final_count:"<>N>>M; rep(i, N){ int aa, bb; cin>>aa>>bb; a.push_back(aa); b.push_back(bb); } vector>>> dist_map = make_dist_map(); vec_int route = find_initial_route(dist_map); tsp(route, dist_map); vector stations(M); rep(i, M){ stations.at(i) = SpaceStation(ro.get_rand(0, 1001), ro.get_rand(0, 1001)); } vec_int keiyu_flag = annealing(route, stations, dist_map); /* int current_reduction = check_keiyu(stations, keiyu_flag, route, dist_map); vec_int best_keiyu; while(true){ float ct = get_time(false); if(ct>180)break; int ind = ro.get_rand(0, M); int original_x = stations.at(ind).x; int original_y = stations.at(ind).y; int dx = ro.get_rand(-50, 51); int dy = ro.get_rand(-50, 51); int x2 = original_x + dx; int y2 = original_y + dy; x2 = min(1000, x2); y2 = min(1000, y2); x2 = max(0, x2); y2 = max(0, y2); stations.at(ind).x = x2; stations.at(ind).y = y2; int after_reduction = check_keiyu(stations, keiyu_flag, route, dist_map); int diff = after_reduction - current_reduction; if(diff>=0){ current_reduction = after_reduction; best_keiyu = keiyu_flag; }else{ stations.at(ind).x = original_x; stations.at(ind).y = original_y; } } */ rep(i, M){ cout<