#include #include #include #include #include #include #include #include #include using namespace std; using ll = long long; mt19937_64 mt(1); const int N = 47; const int R = 1000; const int M = 400; const int K = 25; int convert_time_int(string s) { assert(s.size() == 5); assert('0' <= s[0] && s[0] <= '9'); assert('0' <= s[1] && s[1] <= '9'); assert(s[2] == ':'); assert('0' <= s[3] && s[3] <= '9'); assert('0' <= s[4] && s[4] <= '9'); int h = int(s[0] - '0') * 10 + int(s[1] - '0'); int m = int(s[3] - '0') * 10 + int(s[4] - '0'); assert(make_pair(h, m) >= make_pair(6, 0)); assert(make_pair(h, m) <= make_pair(21, 0)); assert(m % 5 == 0); return (h - 6) * 12 + (m / 5); } string convert_int_time(int x) { assert(0 <= x && x <= 180); int h = x / 12 + 6; int m = (x % 12) * 5; string res; res += char(h / 10 + '0'); res += char(h % 10 + '0'); res += ':'; res += char(m / 10 + '0'); res += char(m % 10 + '0'); return res; } int sqr(int x) { return x * x; } class city { public: int x, y, w; explicit city() : x(0), y(0), w(0) {} explicit city(int x_, int y_, int w_) : x(x_), y(y_), w(w_) {} }; class route { public: int a, s, b, t; explicit route() : a(-1), s(-1), b(-1), t(-1) {} explicit route(int a_, int s_, int b_, int t_) : a(a_), s(s_), b(b_), t(t_) {} }; int get_norm(const city& c1, const city& c2) { return sqr(c2.x - c1.x) + sqr(c2.y - c1.y); } int req_time(const city& c1, const city& c2) { int norm = get_norm(c1, c2); int res = ceil((60 * sqrt(norm) / 800 + 40) / 5); return res; } vector>> calc_times(const vector& routes) { vector> base_g(N); for (int i = 0; i < int(routes.size()); i++) { base_g[routes[i].b].push_back(i); } vector>> base_time(21, vector>(N)); for (int i = 0; i <= 20; i++) { int start = i * 6 + 60; for (int j = 0; j < N; j++) { vector d(N, -1); d[j] = start; priority_queue> que; que.emplace(start, j); while (!que.empty()) { auto [t, u] = que.top(); que.pop(); if (d[u] == t) { vector best_s(N, -1); for (int k : base_g[u]) { const route& r = routes[k]; if (r.t <= t) { best_s[r.a] = max(best_s[r.a], r.s); } } for (int k = 0; k < N; k++) { if (d[k] < best_s[k]) { d[k] = best_s[k]; que.emplace(d[k], k); } } } } base_time[i][j] = d; } } return base_time; } vector flatten(const vector>& ans) { vector res; for (const vector& v : ans) { for (const route& r : v) { res.push_back(r); } } return res; } pair get_base_score(const vector& cities, const vector>>& sq_time, const vector>>& ci_time) { ll sq_val = 0; ll ci_val = 0; for (int i = 0; i < 21; i++) { for (int j = 0; j < N; j++) { for (int k = 0; k < N; k++) { int norm = get_norm(cities[j], cities[k]); if (norm * 16 >= R * R) { if (ci_time[i][j][k] > sq_time[i][j][k]) { ci_val += (ll)(cities[j].w) * cities[k].w; } else { sq_val += (ll)(cities[j].w) * cities[k].w; } } } } } return make_pair(sq_val, ci_val); } vector> solve(const vector& cities, const vector& routes) { // step #1. calculate distances vector> cost(N, vector(N)); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { if (i != j) { cost[i][j] = req_time(cities[i], cities[j]); } } } vector> far(N, vector(N)); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { far[i][j] = (get_norm(cities[i], cities[j]) * 16 >= R * R); } } vector>> sq_time = calc_times(routes); // step #2. find optimal hub pair hub_opt = make_pair(7LL << 58, -1); for (int i = 0; i < N; i++) { ll total = 0; for (int j = 0; j < N; j++) { for (int k = j + 1; k < N; k++) { if (far[j][k]) { int d = cost[j][i] + cost[k][i]; total += (ll)(d) * cities[j].w * cities[k].w; } } } hub_opt = min(hub_opt, make_pair(total, i)); } int start = hub_opt.second; cerr << "hub = " << start << endl; // step #3. greedy algorithm vector> ans(K); vector cur_time(K, 180); vector last_reach(N, 21); vector>> win(21, vector>(N, vector(N, false))); for (int i = 0; i < K; i++) { int id = i + int(i >= start); ans[i].push_back(route(start, 180 - cost[id][start], id, 180)); cur_time[i] = 180 - cost[id][start]; last_reach[id] = 20; } ll cur_score = 0; while (true) { int id = max_element(cur_time.begin(), cur_time.end()) - cur_time.begin(); pair best = make_pair(ll(-1), -1); for (int j = 0; j < N; j++) { if (j != start) { int t = cur_time[id] - 2 * cost[j][start]; if (t >= 0) { ll delta = 0; for (int k = 0; k < N; k++) { if (k != start && far[j][k]) { for (int l = last_reach[k]; l <= 20; l++) { if (!win[l][j][k] && t > sq_time[l][j][k]) { delta += (ll)(cities[j].w) * cities[k].w; } } } } best = max(best, make_pair(delta, j)); } } } // cerr << best.first << " " << best.second << endl; int pos = best.second; if (pos == -1) { break; } int pos_time = cur_time[id] - 2 * cost[pos][start]; for (int j = 0; j < N; j++) { if (j != start && far[j][pos]) { for (int k = last_reach[j]; k <= 20; k++) { if (!win[k][pos][j] && pos_time > sq_time[k][pos][j]) { win[k][pos][j] = true; } } } } ans[id].push_back(route(pos, cur_time[id] - cost[pos][start], start, cur_time[id])); ans[id].push_back(route(start, cur_time[id] - 2 * cost[pos][start], pos, cur_time[id] - cost[pos][start])); cur_time[id] -= 2 * cost[pos][start]; last_reach[pos] = max(cur_time[id] - 60, 0) / 5; } for (int i = 0; i < K; i++) { reverse(ans[i].begin(), ans[i].end()); } return ans; } void output_score(const vector& cities, const vector& routes, const vector>& ans) { // step #1. check if the answer is valid if (ans.size() != K) { cerr << "wrong answer [1]" << endl; return; } for (int i = 0; i < K; i++) { int rs = ans[i].size(); for (int j = 0; j < rs; j++) { route r = ans[i][j]; if (!(0 <= r.a && r.a < N && 0 <= r.b && r.b < N && 0 <= r.s && r.s <= 180 && 0 <= r.t && r.t <= 180)) { cerr << "wrong answer [2]" << endl; return; } if (r.t - r.s != req_time(cities[r.a], cities[r.b])) { cerr << "wrong answer [3]" << endl; return; } if (j >= 1) { route pr = ans[i][j - 1]; if (!(pr.b == r.a && pr.t <= r.s)) { cerr << "wrong answer [4]" << endl; return; } } } } // step #2. compute score vector>> sq_time = calc_times(routes); vector>> ci_time = calc_times(flatten(ans)); auto [sq_val, ci_val] = get_base_score(cities, sq_time, ci_time); double share = double(ci_val) / (sq_val + ci_val); cerr << "sq_val = " << sq_val << endl; cerr << "ci_val = " << ci_val << endl; cerr << "score = " << int(share * 1000000) << endl; } int main() { int TMP_N, TMP_R, TMP_M, TMP_K; cin >> TMP_N >> TMP_R; vector cities(N); for (int i = 0; i < N; i++) { cin >> cities[i].x >> cities[i].y >> cities[i].w; } cin >> TMP_M; vector routes(M); for (int i = 0; i < M; i++) { int a, b; string cs, ct; cin >> a >> cs >> b >> ct; routes[i].a = a - 1; routes[i].s = convert_time_int(cs); routes[i].b = b - 1; routes[i].t = convert_time_int(ct); } vector> ans = solve(cities, routes); for (int i = 0; i < K; i++) { cout << ans[i].size() << endl; for (const route& r : ans[i]) { cout << r.a + 1 << ' ' << convert_int_time(r.s) << ' ' << r.b + 1 << ' ' << convert_int_time(r.t) << endl; } } output_score(cities, routes, ans); return 0; }