#include using namespace std; static constexpr int START_MIN = 6 * 60; static constexpr int END_MIN = 21 * 60; static constexpr int STEP_MIN = 5; static constexpr int TICK_MAX = (END_MIN - START_MIN) / STEP_MIN; // 180 static constexpr int NEG_INF = -1; struct City { int x, y; long long w; }; struct Flight { int a, b; // 0-based city int s, t; // tick [0..180] }; struct Candidate { bool valid = false; int b = -1; int t = -1; int dur = -1; long long delta = LLONG_MIN; long long potential = LLONG_MIN; long long pop = LLONG_MIN; }; struct XorShift { uint64_t x = 88172645463325252ULL; uint64_t next_u64() { x ^= x << 7; x ^= x >> 9; return x; } int next_int(int lo, int hi) { return lo + (int)(next_u64() % (uint64_t)(hi - lo + 1)); } double next_double() { return (next_u64() >> 11) * (1.0 / 9007199254740992.0); } }; static int time_to_idx(const string &hhmm) { int hh = stoi(hhmm.substr(0, 2)); int mm = stoi(hhmm.substr(3, 2)); int mins = hh * 60 + mm; return (mins - START_MIN) / STEP_MIN; } static string idx_to_time(int idx) { int mins = START_MIN + idx * STEP_MIN; int hh = mins / 60; int mm = mins % 60; ostringstream oss; oss << setw(2) << setfill('0') << hh << ":" << setw(2) << setfill('0') << mm; return oss.str(); } static int duration_ticks(const City &c1, const City &c2) { double dx = double(c1.x - c2.x); double dy = double(c1.y - c2.y); double dist = sqrt(dx * dx + dy * dy); double raw = 60.0 * dist / 800.0 + 40.0; int rounded = int(ceil(raw / 5.0 - 1e-12) * 5.0); return rounded / 5; } static inline int latest_idx(int n, int dcount, int dest, int dk, int orig) { return ((dest * dcount) + dk) * n + orig; } static void compute_latest_all_sorted( int n, const vector &deadlines, const vector &flights_desc, vector &latest_out) { const int dcount = (int)deadlines.size(); latest_out.assign(n * dcount * n, NEG_INF); for (int dest = 0; dest < n; dest++) { for (int dk = 0; dk < dcount; dk++) { int deadline = deadlines[dk]; int base = latest_idx(n, dcount, dest, dk, 0); int *L = &latest_out[base]; fill(L, L + n, NEG_INF); L[dest] = deadline; for (const auto &f : flights_desc) { if (f.t > deadline) { continue; } if (L[f.b] >= f.t && f.s > L[f.a]) { L[f.a] = f.s; } } } } } static long long evaluate_vci( int n, const vector &deadlines, const vector &sq_latest, const vector &ci_latest, const vector>> &relevant_dests) { const int dcount = (int)deadlines.size(); long long vci = 0; for (int orig = 0; orig < n; orig++) { for (const auto &[dest, wprod] : relevant_dests[orig]) { for (int dk = 0; dk < dcount; dk++) { int sq = sq_latest[latest_idx(n, dcount, dest, dk, orig)]; int ci = ci_latest[latest_idx(n, dcount, dest, dk, orig)]; if (sq < ci) { vci += wprod; } } } } return vci; } static long long estimate_delta_origin_only( int n, const vector &deadlines, const vector &sq_latest, const vector &ci_latest, const vector>> &relevant_dests, int a, int b, int s, int t) { const int dcount = (int)deadlines.size(); long long delta = 0; for (const auto &[dest, wprod] : relevant_dests[a]) { for (int dk = 0; dk < dcount; dk++) { int idx_b = latest_idx(n, dcount, dest, dk, b); if (ci_latest[idx_b] < t) { continue; } int idx_a = latest_idx(n, dcount, dest, dk, a); int old_ci = ci_latest[idx_a]; if (old_ci >= s) { continue; } int sq = sq_latest[idx_a]; bool old_win = (sq < old_ci); bool new_win = (sq < s); if (!old_win && new_win) { delta += wprod; } } } return delta; } static bool better_candidate(const Candidate &lhs, const Candidate &rhs) { if (!lhs.valid) return false; if (!rhs.valid) return true; if (lhs.delta != rhs.delta) return lhs.delta > rhs.delta; if (lhs.potential != rhs.potential) return lhs.potential > rhs.potential; if (lhs.pop != rhs.pop) return lhs.pop > rhs.pop; if (lhs.dur != rhs.dur) return lhs.dur < rhs.dur; return lhs.b < rhs.b; } static vector build_legs_from_route( int start_city, int start_tick, const vector &route, const vector> &dur) { vector legs; int cur_city = start_city; int cur_t = start_tick; for (int dest : route) { if (dest < 0 || dest >= (int)dur.size()) { continue; } if (dest == cur_city) { continue; } int d = dur[cur_city][dest]; if (d <= 0) { continue; } int arr = cur_t + d; if (arr > TICK_MAX) { break; } legs.push_back(Flight{cur_city, dest, cur_t, arr}); cur_city = dest; cur_t = arr; } return legs; } static vector route_from_legs(const vector &legs) { vector r; r.reserve(legs.size()); for (const auto &f : legs) { r.push_back(f.b); } return r; } static vector flatten_desc(const vector> &plane_legs) { vector all; size_t total = 0; for (const auto &v : plane_legs) { total += v.size(); } all.reserve(total); for (const auto &v : plane_legs) { for (const auto &f : v) { all.push_back(f); } } sort(all.begin(), all.end(), [](const Flight &p, const Flight &q) { if (p.s != q.s) return p.s > q.s; return p.t > q.t; }); return all; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); auto solver_start = chrono::steady_clock::now(); auto elapsed_sec = [&]() { auto now = chrono::steady_clock::now(); return chrono::duration(now - solver_start).count(); }; const double TOTAL_LIMIT_SEC = 0.90; int n, r; cin >> n >> r; vector cities(n); for (int i = 0; i < n; i++) { cin >> cities[i].x >> cities[i].y >> cities[i].w; } int m; cin >> m; vector square(m); for (int i = 0; i < m; i++) { int a, b; string ss, tt; cin >> a >> ss >> b >> tt; --a; --b; square[i] = Flight{a, b, time_to_idx(ss), time_to_idx(tt)}; } int k; cin >> k; vector> dur(n, vector(n, 0)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i == j) continue; dur[i][j] = duration_ticks(cities[i], cities[j]); } } vector deadlines; { int base = (11 * 60 - START_MIN) / STEP_MIN; for (int t = 0; t < 21; t++) { deadlines.push_back(base + t * 6); } } vector square_desc = square; sort(square_desc.begin(), square_desc.end(), [](const Flight &p, const Flight &q) { if (p.s != q.s) return p.s > q.s; return p.t > q.t; }); vector sq_latest; compute_latest_all_sorted(n, deadlines, square_desc, sq_latest); vector>> relevant_dests(n); { long long rr = 1LL * r * r; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { long long dx = 1LL * cities[i].x - cities[j].x; long long dy = 1LL * cities[i].y - cities[j].y; long long d2 = dx * dx + dy * dy; if (16LL * d2 >= rr) { relevant_dests[i].push_back({j, cities[i].w * cities[j].w}); } } } } vector> need_score(n, vector(TICK_MAX + 1, 0)); { const int dcount = (int)deadlines.size(); for (int orig = 0; orig < n; orig++) { for (int s = 0; s <= TICK_MAX; s++) { long long val = 0; for (const auto &[dest, wprod] : relevant_dests[orig]) { for (int dk = 0; dk < dcount; dk++) { int sq = sq_latest[latest_idx(n, dcount, dest, dk, orig)]; if (sq < s) { val += wprod; } } } need_score[orig][s] = val; } } } vector order(n); iota(order.begin(), order.end(), 0); sort(order.begin(), order.end(), [&](int a, int b) { return cities[a].w > cities[b].w; }); vector plane_start_city(k); vector plane_city(k), plane_time(k, 0); vector> plane_legs(k); for (int p = 0; p < k; p++) { plane_start_city[p] = order[p % n]; plane_city[p] = plane_start_city[p]; } vector circle_desc; vector ci_latest; compute_latest_all_sorted(n, deadlines, circle_desc, ci_latest); auto insert_flight_desc = [&](const Flight &f) { auto it = lower_bound( circle_desc.begin(), circle_desc.end(), f, [](const Flight &x, const Flight &y) { if (x.s != y.s) return x.s > y.s; return x.t > y.t; }); circle_desc.insert(it, f); }; int steps = 0; while (true) { if (elapsed_sec() >= TOTAL_LIMIT_SEC - 0.04) { break; } int p = -1; int best_time = TICK_MAX + 1; for (int i = 0; i < k; i++) { if (plane_time[i] <= TICK_MAX && plane_time[i] < best_time) { best_time = plane_time[i]; p = i; } } if (p < 0) { break; } int a = plane_city[p]; int s = plane_time[p]; Candidate best; best.valid = false; for (int b = 0; b < n; b++) { if (b == a) continue; int d = dur[a][b]; if (d <= 0) continue; int t = s + d; if (t > TICK_MAX) continue; long long delta = estimate_delta_origin_only( n, deadlines, sq_latest, ci_latest, relevant_dests, a, b, s, t); long long potential = need_score[b][t]; Candidate cand; cand.valid = true; cand.b = b; cand.t = t; cand.dur = d; cand.delta = delta; cand.potential = potential; cand.pop = cities[b].w; if (better_candidate(cand, best)) { best = cand; } } if (!best.valid) { plane_time[p] = TICK_MAX + 1; continue; } if (best.delta <= 0 && best.potential <= 0) { plane_time[p] = TICK_MAX + 1; continue; } Flight f{a, best.b, s, best.t}; plane_legs[p].push_back(f); insert_flight_desc(f); plane_city[p] = best.b; plane_time[p] = best.t; steps++; compute_latest_all_sorted(n, deadlines, circle_desc, ci_latest); } long long greedy_vci = evaluate_vci(n, deadlines, sq_latest, ci_latest, relevant_dests); // ---- Windowed local SA improvement ---- vector> cur_routes(k); for (int p = 0; p < k; p++) { cur_routes[p] = route_from_legs(plane_legs[p]); } vector> cur_legs = plane_legs; long long cur_score = greedy_vci; vector> best_legs = cur_legs; long long best_score = cur_score; auto recompute_score = [&](const vector> &legs) -> long long { vector desc = flatten_desc(legs); vector latest; compute_latest_all_sorted(n, deadlines, desc, latest); return evaluate_vci(n, deadlines, sq_latest, latest, relevant_dests); }; vector windows; const int WINDOW_STEP = 6; // 30 min const int WINDOW_SIZE = 24; // 2 hours for (int t = 0; t <= TICK_MAX; t += WINDOW_STEP) { windows.push_back(t); } XorShift rng; double remain = TOTAL_LIMIT_SEC - elapsed_sec(); int sa_attempts = 0; int sa_accepts = 0; int sa_improves = 0; int win_ptr = 0; if (remain > 0.03) { double sa_start = elapsed_sec(); double sa_limit = TOTAL_LIMIT_SEC - 0.003; const double LOG_T0 = log(5e13); const double LOG_T1 = log(5e10); while (elapsed_sec() < sa_limit) { sa_attempts++; int w0 = windows[win_ptr]; win_ptr++; if (win_ptr >= (int)windows.size()) win_ptr = 0; int w1 = min(TICK_MAX + 1, w0 + WINDOW_SIZE); int p = -1; vector mutable_idx; for (int trial = 0; trial < k; trial++) { int cand_p = rng.next_int(0, k - 1); mutable_idx.clear(); for (int idx = 0; idx < (int)cur_legs[cand_p].size(); idx++) { int s = cur_legs[cand_p][idx].s; if (w0 <= s && s < w1) { mutable_idx.push_back(idx); } } if (!mutable_idx.empty()) { p = cand_p; break; } } if (p < 0) { continue; } vector cand_route = cur_routes[p]; if (cand_route.empty()) { continue; } int idx = mutable_idx[rng.next_int(0, (int)mutable_idx.size() - 1)]; if (idx < 0 || idx >= (int)cand_route.size()) { continue; } auto mutate_at = [&](int pos) { int dep = (pos == 0 ? plane_start_city[p] : cand_route[pos - 1]); int old = cand_route[pos]; int L = min(n, 20); int next_city = -1; for (int tr = 0; tr < 24; tr++) { int b; if (rng.next_double() < 0.80) { b = order[rng.next_int(0, L - 1)]; } else { b = rng.next_int(0, n - 1); } if (b != dep && b != old) { next_city = b; break; } } if (next_city >= 0) { cand_route[pos] = next_city; } }; mutate_at(idx); if (rng.next_double() < 0.20 && !mutable_idx.empty()) { int idx2 = mutable_idx[rng.next_int(0, (int)mutable_idx.size() - 1)]; if (idx2 >= 0 && idx2 < (int)cand_route.size()) { mutate_at(idx2); } } vector cand_legs_p = build_legs_from_route(plane_start_city[p], 0, cand_route, dur); cand_route = route_from_legs(cand_legs_p); vector> nxt_legs = cur_legs; nxt_legs[p] = std::move(cand_legs_p); long long nxt_score = recompute_score(nxt_legs); long long delta = nxt_score - cur_score; double progress = (elapsed_sec() - sa_start) / max(1e-9, (sa_limit - sa_start)); progress = min(1.0, max(0.0, progress)); double temp = exp(LOG_T0 * (1.0 - progress) + LOG_T1 * progress); bool accept = false; if (delta >= 0) { accept = true; } else { double x = (double)delta / temp; if (x > -50.0 && rng.next_double() < exp(x)) { accept = true; } } if (!accept) { continue; } sa_accepts++; cur_score = nxt_score; cur_legs = std::move(nxt_legs); cur_routes[p] = std::move(cand_route); if (cur_score > best_score) { best_score = cur_score; best_legs = cur_legs; sa_improves++; } } } cerr << "[summary] greedy_v_ci=" << greedy_vci << " best_v_ci=" << best_score << " sa_attempts=" << sa_attempts << " sa_accepts=" << sa_accepts << " sa_improves=" << sa_improves << " elapsed=" << elapsed_sec() << "s\n"; for (int p = 0; p < k; p++) { cout << best_legs[p].size() << '\n'; for (const auto &f : best_legs[p]) { cout << (f.a + 1) << ' ' << idx_to_time(f.s) << ' ' << (f.b + 1) << ' ' << idx_to_time(f.t) << '\n'; } } return 0; }