#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>> sq_time = calc_times(routes); // step #2. construction vector sum_pop(N + 1); for (int i = 0; i < N; i++) { sum_pop[i + 1] = sum_pop[i] + cities[i].w; } auto rand_city = [&]() -> int { double z = double(mt()) / double(uint64_t(-1)); int pos = lower_bound(sum_pop.begin(), sum_pop.end(), int(z * sum_pop[N])) - sum_pop.begin() - 1; return pos; }; const int MAX_LOOPS = 300; vector> ans(K); int loops = 0; ll cur_ci_val = 0; while (loops < MAX_LOOPS) { loops++; int id = mt() % K; vector pre_ans = ans[id]; ans[id].clear(); int start = rand_city(); int t = 0, v = start; while (true) { vector possible(N); for (int j = 0; j < N; j++) { possible[j] = (t + cost[v][j] <= 180) && (v != j); } if (possible != vector(N, false)) { int nv = -1; do { nv = rand_city(); } while (!possible[nv]); int nt = t + cost[v][nv]; ans[id].push_back(route(v, t, nv, nt)); v = nv; t = nt; } else { break; } } vector>> ci_time = calc_times(flatten(ans)); auto [sq_val, ci_val] = get_base_score(cities, sq_time, ci_time); if (cur_ci_val < ci_val) { double score = double(ci_val) / (sq_val + ci_val); cerr << "#" << loops << ": " << score << endl; cur_ci_val = ci_val; } else { ans[id] = pre_ans; } } 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; }