#include using namespace std; # pragma GCC target("avx2") # pragma GCC optimize("O3") # pragma GCC optimize("unroll-loops") /* 修正版 Main.cpp - 警告・エラー修正済み (std::move, 重複定義削除, 未使用変数削除) - 挙動は以前提示した焼きなまし + 近傍操作の実装と同じ */ struct City { double x, y; long long w; }; struct Flight { int a; int dep; int b; int arr; }; // dep/arr in minutes from midnight int travel_time_minutes(double x1, double y1, double x2, double y2) { double d = hypot(x1 - x2, y1 - y2); double raw = 60.0 * d / 800.0 + 40.0; int tt = (int)ceil(raw / 5.0) * 5; return tt; } string fmt_time(int t){ int hh = t / 60; int mm = t % 60; char buf[6]; sprintf(buf, "%02d:%02d", hh, mm); return string(buf); } const int START = 6*60; // 360 const int END = 21*60; // 1260 const int INF_NEG = -1000000000; // Convert "HH:MM" to minutes int parse_time(const string &s){ int hh = stoi(s.substr(0,2)); int mm = stoi(s.substr(3,2)); return hh*60 + mm; } using Schedule = vector>; // Build list of target arrival times: 11:00..21:00 step 30 vector build_target_times() { vector T; for (int t = 11*60; t <= 21*60; t += 30) T.push_back(t); return T; } // Flatten schedules into flight vector vector flatten_schedule(const Schedule &schedules) { vector flights; for (const auto &sch : schedules) { for (const auto &f : sch) flights.push_back(f); } return flights; } // compute flights_by_arrival mapping for given flights vector> build_flights_by_arrival(const vector &flights, int N) { vector> fba(N); for (int i = 0; i < (int)flights.size(); ++i) { int arr_city = flights[i].b; fba[arr_city].push_back(i); } return fba; } // Given flights (list) and flights_by_arrival, compute for all dest and all target times T the latest departure times // returns res[dest][t_idx][city] = latest departure time from city to reach dest by T (or INF_NEG) vector>> compute_latest_deps_all(int N, const vector &flights, const vector> &fba, const vector &Tlist) { int D = N; int TT = (int)Tlist.size(); vector>> res(D, vector>(TT, vector(N, INF_NEG))); // For each dest and target time, do reverse BFS/DP for (int dest = 0; dest < D; ++dest) { for (int ti = 0; ti < TT; ++ti) { int T = Tlist[ti]; vector L(N, INF_NEG); deque dq; L[dest] = T; dq.push_back(dest); while (!dq.empty()) { int v = dq.front(); dq.pop_front(); // all flights that arrive at v for (int fi : fba[v]) { const Flight &f = flights[fi]; if (f.arr <= L[v]) { int u = f.a; if (L[u] < f.dep) { L[u] = f.dep; dq.push_back(u); } } } } res[dest][ti] = std::move(L); } } return res; } // compute latest_deps for circle (s_ci) given current schedules: returns res[dest][ti][city] vector>> compute_s_ci_all(const Schedule &schedules, const vector &cities, const vector &Tlist) { // flatten flights with indices, build flights_by_arrival vector flights = flatten_schedule(schedules); int N = (int)cities.size(); vector> fba = build_flights_by_arrival(flights, N); // compute latest deps return compute_latest_deps_all(N, flights, fba, Tlist); } // Evaluate share-rate S given precomputed s_sq for Square and computed s_ci for Circle long double compute_share_rate(const vector>> &s_sq_all, const vector>> &s_ci_all, const vector> &ODlist, const vector &Tlist, const vector &cities) { long double v_ci = 0.0L, v_sq = 0.0L; int TT = (int)Tlist.size(); for (auto &od : ODlist) { int u = od.first; int v = od.second; long long weight = cities[u].w * cities[v].w; for (int ti = 0; ti < TT; ++ti) { int s_sq = s_sq_all[v][ti][u]; int s_ci = s_ci_all[v][ti][u]; if (s_sq < s_ci) v_ci += (long double)weight; else v_sq += (long double)weight; } } if (v_ci + v_sq <= 0.0L) return 0.0L; return v_ci / (v_ci + v_sq); } // Build initial schedule as hub <-> top25 (or up to available) round-robin Schedule build_initial(const vector &cities, int K) { int N = cities.size(); // find hub int hub = 0; for (int i = 1; i < N; ++i) if (cities[i].w > cities[hub].w) hub = i; // sort others by pop vector> vec; for (int i = 0; i < N; ++i) if (i != hub) vec.emplace_back(cities[i].w, i); sort(vec.begin(), vec.end(), [](const auto &A, const auto &B){ if (A.first != B.first) return A.first > B.first; return A.second < B.second; }); int needSpokes = 25; int topCount = min((int)vec.size(), needSpokes); vector targets; for (int i = 0; i < topCount; ++i) targets.push_back(vec[i].second); Schedule schedules(K); if (topCount == 0) return schedules; for (int k = 0; k < K; ++k) { int target = targets[k % topCount]; int cur = hub; int time = START; while (true) { int next = (cur == hub) ? target : hub; int tt = travel_time_minutes(cities[cur].x, cities[cur].y, cities[next].x, cities[next].y); int dep = time; int arr = dep + tt; if (arr > END) break; schedules[k].push_back({cur, dep, next, arr}); cur = next; time = arr; } } return schedules; } // Greedy extend from (cur, time) for a single plane vector greedy_extend_from(const vector &cities, int cur, int time) { vector res; int N = cities.size(); while (true) { int best = -1, best_tt = INT_MAX; for (int j = 0; j < N; ++j) { if (j == cur) continue; int tt = travel_time_minutes(cities[cur].x, cities[cur].y, cities[j].x, cities[j].y); if (time + tt > END) continue; if (tt < best_tt || (tt == best_tt && j < best)) { best_tt = tt; best = j; } } if (best == -1) break; int dep = time; int arr = dep + best_tt; res.push_back({cur, dep, best, arr}); cur = best; time = arr; } return res; } // Attempt neighbor operations on schedules (modify only one plane's schedule minimally). // Returns pair : whether changed, and index of plane changed pair apply_random_neighbor(Schedule &schedules, const vector &cities, mt19937_64 &rng) { int K = schedules.size(); uniform_int_distribution pick_plane(0, max(0, K-1)); int k = pick_plane(rng); vector &sch = schedules[k]; int n = sch.size(); uniform_int_distribution opdist(0,1); int op = opdist(rng); if (n == 0) { int hub = 0; for (int i = 1; i < (int)cities.size(); ++i) if (cities[i].w > cities[hub].w) hub = i; vector newsch = greedy_extend_from(cities, hub, START); if (!newsch.empty()) { sch = std::move(newsch); return {true, k}; } else return {false, -1}; } vector backup = sch; if (op == 0) { // change destination of random flight p uniform_int_distribution pick_pos(0, n-1); int p = pick_pos(rng); int cur; int time; if (p == 0) { cur = sch[0].a; time = sch[0].dep; } else { cur = sch[p-1].b; time = sch[p-1].arr; } vector cand; int N = cities.size(); for (int j = 0; j < N; ++j) { if (j == cur) continue; int tt = travel_time_minutes(cities[cur].x, cities[cur].y, cities[j].x, cities[j].y); if (time + tt <= END) cand.push_back(j); } if (cand.empty()) return {false, -1}; int cur_b = sch[p].b; vector cand2; for (int v : cand) if (v != cur_b) cand2.push_back(v); if (cand2.empty()) return {false, -1}; uniform_int_distribution pick_cand(0, (int)cand2.size()-1); int newdest = cand2[pick_cand(rng)]; sch.erase(sch.begin() + p, sch.end()); int tt = travel_time_minutes(cities[cur].x, cities[cur].y, cities[newdest].x, cities[newdest].y); int dep = time; int arr = dep + tt; sch.push_back({cur, dep, newdest, arr}); int cur_city = newdest; int cur_time = arr; // attempt to preserve suffix from backup where possible for (int j = p+1; j < (int)backup.size(); ++j) { const Flight &orig = backup[j]; int required_tt = travel_time_minutes(cities[orig.a].x, cities[orig.a].y, cities[orig.b].x, cities[orig.b].y); if (orig.a == cur_city && orig.dep >= cur_time && orig.arr - orig.dep == required_tt) { sch.push_back(orig); cur_city = orig.b; cur_time = orig.arr; } else { vector tail = greedy_extend_from(cities, cur_city, cur_time); sch.insert(sch.end(), tail.begin(), tail.end()); break; } } return {true, k}; } else { // shift departure of random flight p by +/-5 uniform_int_distribution pick_pos(0, n-1); int p = pick_pos(rng); int prev_arr = (p==0) ? START : sch[p-1].arr; int dep = sch[p].dep; int tt = sch[p].arr - sch[p].dep; vector cand_dep; if (dep - 5 >= prev_arr) cand_dep.push_back(dep - 5); if (dep + 5 + tt <= END) cand_dep.push_back(dep + 5); if (cand_dep.empty()) return {false, -1}; uniform_int_distribution pickd(0, (int)cand_dep.size()-1); int new_dep = cand_dep[pickd(rng)]; int new_arr = new_dep + tt; int a_orig = sch[p].a; int b_orig = sch[p].b; sch.erase(sch.begin() + p, sch.end()); sch.push_back({a_orig, new_dep, b_orig, new_arr}); int cur_city = b_orig; int cur_time = new_arr; for (int j = p+1; j < (int)backup.size(); ++j) { const Flight &orig = backup[j]; int required_tt = travel_time_minutes(cities[orig.a].x, cities[orig.a].y, cities[orig.b].x, cities[orig.b].y); if (orig.a == cur_city && orig.dep >= cur_time && orig.arr - orig.dep == required_tt) { sch.push_back(orig); cur_city = orig.b; cur_time = orig.arr; } else { vector tail = greedy_extend_from(cities, cur_city, cur_time); sch.insert(sch.end(), tail.begin(), tail.end()); break; } } return {true, k}; } } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int N; int R; if (!(cin >> N >> R)) return 0; vector cities(N); for (int i = 0; i < N; ++i) { long long xi, yi, wi; cin >> xi >> yi >> wi; cities[i].x = (double)xi; cities[i].y = (double)yi; cities[i].w = wi; } int M; cin >> M; vector square_flights; square_flights.reserve(M); for (int i = 0; i < M; ++i) { int a, b; string s_str, t_str; cin >> a >> s_str >> b >> t_str; int smin = parse_time(s_str); int tmin = parse_time(t_str); square_flights.push_back({a-1, smin, b-1, tmin}); } int K; cin >> K; // Precompute Tlist and ODlist (pairs with distance >= 0.25R) vector Tlist = build_target_times(); vector> ODlist; for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { if (i == j) continue; double d = hypot(cities[i].x - cities[j].x, cities[i].y - cities[j].y); if (d + 1e-9 >= 0.25 * (double)R) ODlist.emplace_back(i,j); } } // Precompute s_sq_all using square_flights vector> fba_sq = build_flights_by_arrival(square_flights, N); vector>> s_sq_all = compute_latest_deps_all(N, square_flights, fba_sq, Tlist); // Build initial schedules Schedule schedules = build_initial(cities, K); // Evaluate initial s_ci and share-rate vector>> s_ci_all = compute_s_ci_all(schedules, cities, Tlist); long double best_score = compute_share_rate(s_sq_all, s_ci_all, ODlist, Tlist, cities); Schedule best_sched = schedules; // Random mt19937_64 rng((unsigned)chrono::high_resolution_clock::now().time_since_epoch().count()); // Annealing / local search parameters & time control const double TIME_LIMIT = 0.95; // seconds const long double T0 = 1.0L; // initial temperature const long double Tmin = 1e-6L; auto time_start = chrono::high_resolution_clock::now(); while (true) { auto now = chrono::high_resolution_clock::now(); double elapsed = chrono::duration_cast>(now - time_start).count(); if (elapsed > TIME_LIMIT) break; long double frac = elapsed / TIME_LIMIT; if (frac > 1.0) frac = 1.0; long double T = T0 * (1.0L - frac) + Tmin * frac; Schedule old_sched = schedules; auto res = apply_random_neighbor(schedules, cities, rng); if (!res.first) { schedules = old_sched; continue; } // compute s_ci_all for new schedules (full recompute) vector>> new_s_ci_all = compute_s_ci_all(schedules, cities, Tlist); long double new_score = compute_share_rate(s_sq_all, new_s_ci_all, ODlist, Tlist, cities); bool accept = false; if (new_score > best_score) { accept = true; best_score = new_score; best_sched = schedules; } else { long double diff = new_score - best_score; // <= 0 long double prob = expl(diff / max((long double)1e-18, T)); uniform_real_distribution ud(0.0L, 1.0L); if (ud(rng) < prob) accept = true; else accept = false; } if (!accept) { schedules = old_sched; // revert } } // Output best solution in required format for (int k = 0; k < K; ++k) { if (k < (int)best_sched.size()) { const auto &sch = best_sched[k]; cout << sch.size() << '\n'; for (const auto &f : sch) { cout << (f.a + 1) << " " << fmt_time(f.dep) << " " << (f.b + 1) << " " << fmt_time(f.arr) << '\n'; } } else { cout << 0 << '\n'; } } return 0; }