結果
問題 | No.5007 Steiner Space Travel |
ユーザー | yunix |
提出日時 | 2022-08-02 22:54:10 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 987 ms / 1,000 ms |
コード長 | 22,853 bytes |
コンパイル時間 | 2,155 ms |
実行使用メモリ | 4,980 KB |
スコア | 8,703,843 |
最終ジャッジ日時 | 2022-08-02 22:54:45 |
合計ジャッジ時間 | 35,087 ms |
ジャッジサーバーID (参考情報) |
judge12 / judge11 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 986 ms
4,904 KB |
testcase_01 | AC | 986 ms
4,920 KB |
testcase_02 | AC | 986 ms
4,964 KB |
testcase_03 | AC | 986 ms
4,820 KB |
testcase_04 | AC | 986 ms
4,776 KB |
testcase_05 | AC | 986 ms
4,904 KB |
testcase_06 | AC | 986 ms
4,976 KB |
testcase_07 | AC | 986 ms
4,904 KB |
testcase_08 | AC | 986 ms
4,888 KB |
testcase_09 | AC | 986 ms
4,964 KB |
testcase_10 | AC | 985 ms
4,964 KB |
testcase_11 | AC | 986 ms
4,940 KB |
testcase_12 | AC | 987 ms
4,956 KB |
testcase_13 | AC | 986 ms
4,828 KB |
testcase_14 | AC | 987 ms
4,924 KB |
testcase_15 | AC | 986 ms
4,980 KB |
testcase_16 | AC | 987 ms
4,808 KB |
testcase_17 | AC | 986 ms
4,900 KB |
testcase_18 | AC | 986 ms
4,916 KB |
testcase_19 | AC | 986 ms
4,824 KB |
testcase_20 | AC | 986 ms
4,904 KB |
testcase_21 | AC | 986 ms
4,856 KB |
testcase_22 | AC | 986 ms
4,876 KB |
testcase_23 | AC | 987 ms
4,876 KB |
testcase_24 | AC | 986 ms
4,932 KB |
testcase_25 | AC | 987 ms
4,880 KB |
testcase_26 | AC | 986 ms
4,896 KB |
testcase_27 | AC | 986 ms
4,800 KB |
testcase_28 | AC | 987 ms
4,928 KB |
testcase_29 | AC | 985 ms
4,784 KB |
ソースコード
#include <iostream> #include <string> #include <vector> #include <tuple> #include <chrono> #include <algorithm> #include <random> #include <map> #include <set> #include <queue> #include <random> #include <chrono> #include <cmath> #include <climits> using namespace std; using vec_int = vector<int>; using P = pair<int, int>; using T = tuple<int, int, int>; using ll = long long; // using PQ = priority_queue<pair<float, int>, vector<pair<float,int>>, greater<pair<float, int>>>; #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<P> 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<int> 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<std::chrono::milliseconds>(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"<<t<<" "<<diff<<endl; return rand < exp(((float)diff) / t); } float current_tmp_tsp(float current_time) { return final_T + (initial_T - final_T) * (TIME_LIMIT - current_time) / TIME_LIMIT; } bool is_valid_transition_tsp(int diff, float current_time) { float t = current_tmp_tsp(current_time); float rand = ro.get_float(); return rand < exp(((float)diff) / t); } float current_tmp_tsp2(float current_time) { return final_T + (initial_T - final_T) * (TIME_LIMIT_TSP2 - current_time) / TIME_LIMIT_TSP2; } bool is_valid_transition_tsp2(int diff, float current_time) { float t = current_tmp_tsp2(current_time); float rand = ro.get_float(); return rand < exp(((float)diff) / t); } int N, M; vec_int a, b; int alpha=5; int sq_alpha=25; class SpaceStation{ public: int x; int y; SpaceStation(){ x=0; y=0; }; SpaceStation(int xpos, int ypos){ x=xpos; y=ypos; }; int square_distance(int x2, int y2){ return (x2-x)*(x2-x) + (y2-y)*(y2-y); }; void set_pos(int xpos, int ypos){ x=xpos; y=ypos; }; void random_move(){ int dx = ro.get_rand(-20, 21); int dy = ro.get_rand(-20, 21); int x2 = x+dx; int y2 = y+dy; x2 = max(0, x2); y2 = max(0, y2); x2 = min(1000, x2); y2 = min(1000, y2); x=x2; y=y2; }; int intermediate_distance(int city1, int city2){ int result = 0; result += square_distance(a.at(city1), b.at(city1))*alpha; result += square_distance(a.at(city2), b.at(city2))*alpha; return result; } }; int tot_distance(vector<SpaceStation> &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<vector<pair<int, vector<P>>>> make_dist_map(){ vector<vector<pair<int, vector<P>>>> result(N, vector<pair<int, vector<P>>>(N)); vector<vector<int>> visited(N, vec_int(N, 0)); for(int i=0;i<N;i++){ // 都市iをstartにする priority_queue<T, vector<T>, greater<T>> 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<P> 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<P> route2 = route; reverse(route2.begin(), route2.end()); result.at(pos).at(i) = make_pair(dist, route2); for(int j=0;j<N;j++){ // 都市にいく時 if(visited.at(i).at(j)==1)continue; int add_dist = sq_dist_between_cities(pos, j) * sq_alpha; pq.emplace(dist+add_dist, j, pos); } } } return result; } int calc_dist(vector<SpaceStation> &stations, vector<P> &tmp_ans){ int result = 0; for(int i=1;i<tmp_ans.size();i++){ int type, pos; tie(type, pos) = tmp_ans.at(i); int prev_type, prev_pos; tie(prev_type, prev_pos) = tmp_ans.at(i-1); if(type==1&&prev_type==1){ result += sq_dist_between_cities(pos, prev_pos)*sq_alpha; }else if(type==1&&prev_type==2){ result += stations.at(prev_pos).square_distance(a.at(pos), b.at(pos))*alpha; }else if(type==2 && prev_type==1){ result += stations.at(pos).square_distance(a.at(prev_pos), b.at(prev_pos))*alpha; }else{ result += stations.at(pos).square_distance(stations.at(prev_pos).x, stations.at(prev_pos).y); } } return result; } int check_keiyu(vector<SpaceStation> &stations, vec_int &keiyu_flag, vec_int &routes, vector<vector<pair<int, vector<P>>>> &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<original_distance){ result += original_distance - after_distance; keiyu_flag.at(i) = keiyu; } } return result; } int greedy_strategy(vector<P> &ans, vector<SpaceStation> &stations, vector<vector<pair<int, vector<P>>>> &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;i<N;i++){ if(visited.at(i)==1)continue; int tmp_dist = dist_mat.at(pos).at(i).first; if(min_dist>tmp_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<SpaceStation> &stations, vector<P> &tmp_ans){ vector<vec_int> 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<M;station++){ int x = stations.at(station).x; int y = stations.at(station).y; int min_dist = INT_MAX; int best_x = x; int best_y = y; for(int dx=-100;dx<=100;dx+=2){ for(int dy=-100;dy<=100;dy+=2){ int tot_dist = 0; int x2 = x+dx; int y2 = y+dy; if(!(0<=x2 && x2<=1000 && 0<=y2 && y2<=1000))continue; stations.at(station).x = x2; stations.at(station).y = y2; for(auto star: station_connections.at(station)){ tot_dist += stations.at(station).square_distance(a.at(star), b.at(star)); } if(tot_dist<min_dist){ min_dist = tot_dist; best_x = x2; best_y = y2; } } } stations.at(station).x=best_x; stations.at(station).y=best_y; } } vector<int> find_initial_route(vector<vector<pair<int, vector<P>>>> &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;i<N;i++){ if(visited.at(i)==1)continue; if(min_dist>dist_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<int> &route, vector<vector<pair<int, vector<P>>>> &dist_map, vec_int &keiyu_flag){ vector<P> result; for(int i=1;i<route.size();i++){ int prev = route.at(i-1); int current = route.at(i); if(keiyu_flag.at(i-1)==-1){ for(auto pos: dist_map.at(prev).at(current).second){ result.push_back(pos); } }else{ result.push_back(make_pair(1, prev)); result.push_back(make_pair(2, keiyu_flag.at(i-1))); result.push_back(make_pair(1, current)); } } cout<<result.size()<<endl; rep(i, result.size()){ cout<<result.at(i).first<<" "<<result.at(i).second+1<<endl; } } void tsp(vec_int &route, vector<vector<pair<int, vector<P>>>> &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<vector<pair<int, vector<P>>>> &dist_map, vec_int &keiyu_flag, vector<SpaceStation> &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<SpaceStation> &stations, vector<vector<pair<int, vector<P>>>> &dist_map){ vec_int distance(N); vec_int keiyu(N, -1); for(int i=0;i<N;i++){ // i - i+1の間で何処か別のところを経由させると良いことがあるかをチェックする int prev = route.at(i); int current = route.at(i+1); int original_distance = dist_map.at(prev).at(current).first; int after_dist = INT_MAX; int keiyu_station = -1; for(int j=0;j<M;j++){ int tmp = stations.at(j).intermediate_distance(prev, current); if(after_dist>tmp){ 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:"<<count<<endl; float ct = get_time(false); if(ct>=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<<city1<<" "<<city2<<endl; int original_distance = distance.at(city1); original_distance += distance.at(city2); int after1 = dist_map.at(route.at(city1)).at(route.at(city2)).first; int keiyu1 = -1; for(int j=0;j<M;j++){ int tmp1 = stations.at(j).intermediate_distance(route.at(city1), route.at(city2)); if(after1>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;j<M;j++){ int tmp2 = stations.at(j).intermediate_distance(route.at(city1+1), route.at(city2+1)); if(after2>tmp2){ after2 = tmp2; keiyu2 = j; } } int diff = (original_distance-(after1+after2)); if(is_valid_transition_tsp(diff, ct)){ // cerr<<"valid"<<endl; tot_distance -= original_distance; tot_distance += after1+after2; vec_int route2 = route; vec_int keiyu_vec2 = keiyu; vec_int distance2 = distance; for(int i=city1+1;i<=city2;i++){ route.at(i) = route2.at(city2-(i-(city1+1))); keiyu.at(i) = keiyu_vec2.at(city2-(i-(city1+1))); distance.at(i) = distance2.at(city2-(i-(city1+1))); keiyu.at(city1) = keiyu1; distance.at(city1) = after1; keiyu.at(city2) = keiyu2; distance.at(city2) = after2; } } }else{ // stationを少し動かす int index = ro.get_rand(0, M); int x2, y2; int original_x = stations.at(index).x; int original_y = stations.at(index).y; if(count%11!=0){ int dx = ro.get_rand(-150, 151); int dy = ro.get_rand(-150, 151); x2 = original_x + dx; y2 = original_y + dy; x2 = min(1000, x2); x2 = max(0, x2); y2 = min(1000, y2); y2 = max(0, y2); }else{ x2 = ro.get_rand(0, 1001); y2 = ro.get_rand(0, 1001); } stations.at(index).x = x2; stations.at(index).y = y2; int diff = 0; //after - before for(int i=0;i<N;i++){ int prev = route.at(i); int current = route.at(i+1); if(keiyu.at(i)==index){ int dist1 = distance.at(i); int tmp = stations.at(index).intermediate_distance(prev, current); tmp = min(tmp, dist_map.at(prev).at(current).first); diff += tmp-dist1; }else{ int dist1 = distance.at(i); int tmp = stations.at(index).intermediate_distance(prev, current); if(dist1>tmp){ diff += tmp-dist1; } } } if(is_valid_transition_station(-1*diff, ct)){ // cerr<<"diff:"<<-1*diff<<endl; for(int i=0;i<N;i++){ int prev = route.at(i); int current = route.at(i+1); if(keiyu.at(i)==index){ int dist1 = distance.at(i); int tmp = stations.at(index).intermediate_distance(prev, current); // tmp = min(tmp, dist_map.at(prev).at(current).first); // diff += tmp-dist1; if(tmp<dist_map.at(prev).at(current).first){ distance.at(i) = tmp; keiyu.at(i) = index; }else{ distance.at(i) = dist_map.at(prev).at(current).first; keiyu.at(i) = -1; } tot_distance -= dist1; tot_distance += distance.at(i); }else{ int dist1 = distance.at(i); int tmp = stations.at(index).intermediate_distance(prev, current); if(dist1>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;i<N;i++){ // i - i+1の間で何処か別のところを経由させると良いことがあるかをチェックする int prev = route.at(i); int current = route.at(i+1); int original_distance = dist_map.at(prev).at(current).first; int after_dist = INT_MAX; int keiyu_station = -1; for(int j=0;j<M;j++){ int tmp = stations.at(j).intermediate_distance(prev, current); if(after_dist>tmp){ 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:"<<count<<endl; return keiyu; } int main(){ get_time(true); cin>>N>>M; rep(i, N){ int aa, bb; cin>>aa>>bb; a.push_back(aa); b.push_back(bb); } vector<vector<pair<int, vector<P>>>> dist_map = make_dist_map(); vec_int route = find_initial_route(dist_map); tsp(route, dist_map); vector<SpaceStation> 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<<stations.at(i).x<<" "<<stations.at(i).y<<endl; } cout_ans(route, dist_map, keiyu_flag); rep(i, N){ cerr<<"i:"<<i<<" "<<route.at(i)<<" "<<keiyu_flag.at(i)<<endl; } return 0; }