# pragma GCC target("avx2") # pragma GCC optimize("O3") # pragma GCC optimize("unroll-loops") #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; using ll = long long; struct City { int x, y; ll w; }; struct Flight { int a, b; int s, t; }; struct PlanePlan { vector route; int offset = 0; int duration = 0; }; struct DemandTerm { int src, dst; long double w; array sq; }; constexpr int START_HOUR = 6; constexpr int END_HOUR = 21; constexpr int SLOT_MIN = 5; constexpr int MAX_SLOT = (END_HOUR - START_HOUR) * 60 / SLOT_MIN; // 180 constexpr int TARGET_CNT = 21; constexpr int TARGET_START = (11 - START_HOUR) * 60 / SLOT_MIN; // 60 constexpr int TARGET_STEP = 30 / SLOT_MIN; // 6 constexpr int NEG_INF = -1e9; int parseTimeToSlot(const string &s) { auto pos = s.find(':'); int hh = stoi(s.substr(0, pos)); int mm = stoi(s.substr(pos + 1)); return (hh * 60 + mm - START_HOUR * 60) / SLOT_MIN; } string slotToTime(int slot) { int total = START_HOUR * 60 + slot * SLOT_MIN; int hh = total / 60; int mm = total % 60; char buf[16]; snprintf(buf, sizeof(buf), "%02d:%02d", hh, mm); return string(buf); } int calcDurationSlot(const City &c1, const City &c2) { double dx = double(c1.x) - double(c2.x); double dy = double(c1.y) - double(c2.y); double d = sqrt(dx * dx + dy * dy); double minutes = 60.0 * d / 800.0 + 40.0; return (int)ceil(minutes / 5.0 - 1e-12); } int routeDuration(const vector &route, const vector> &dur) { int total = 0; for(int i = 1; i < (int)route.size(); ++i) { if(route[i - 1] == route[i]) return MAX_SLOT + 1; total += dur[route[i - 1]][route[i]]; if(total > MAX_SLOT) return total; } return total; } void normalizePlane(PlanePlan &p, const vector> &dur) { if(p.route.empty()) p.route.push_back(0); vector fixed; fixed.reserve(p.route.size()); fixed.push_back(p.route[0]); for(int i = 1; i < (int)p.route.size(); ++i) { if(p.route[i] != p.route[i - 1]) fixed.push_back(p.route[i]); } p.route.swap(fixed); if(p.route.empty()) p.route.push_back(0); p.duration = routeDuration(p.route, dur); while(p.duration > MAX_SLOT && (int)p.route.size() > 1) { p.route.pop_back(); p.duration = routeDuration(p.route, dur); } int lim = max(0, MAX_SLOT - p.duration); p.offset = min(max(0, p.offset), lim); } void appendPlaneFlights(const PlanePlan &p, const vector> &dur, vector &out) { int tm = p.offset; for(int i = 1; i < (int)p.route.size(); ++i) { int a = p.route[i - 1]; int b = p.route[i]; int nt = tm + dur[a][b]; out.push_back({a, b, tm, nt}); tm = nt; } } vector flattenPlans(const vector &plans, const vector> &dur) { vector flights; for(const auto &p : plans) appendPlaneFlights(p, dur, flights); return flights; } struct ScoreEvaluator { int N; uint64_t allMask; explicit ScoreEvaluator(int n) : N(n) { allMask = (N == 64 ? ~0ULL : ((1ULL << N) - 1)); } vector> buildByStart(const vector &flights, int target) const { vector> byStart(target + 1); for(const auto &f : flights) { if(f.s < 0 || f.s > target || f.t < 0 || f.t > target) continue; byStart[f.s].push_back(f); } return byStart; } vector> latestMatrixForTarget(const vector> &byStart, int target) const { vector> reach(target + 1, vector(N, 0ULL)); for(int c = 0; c < N; ++c) reach[target][c] = (1ULL << c); for(int tm = target - 1; tm >= 0; --tm) { for(int c = 0; c < N; ++c) reach[tm][c] = reach[tm + 1][c]; for(const auto &f : byStart[tm]) { reach[tm][f.a] |= reach[f.t][f.b]; } } vector> latest(N, vector(N, NEG_INF)); for(int src = 0; src < N; ++src) { uint64_t rem = allMask; for(int tm = target; tm >= 0 && rem; --tm) { uint64_t m = reach[tm][src] & rem; while(m) { int dst = __builtin_ctzll(m); latest[src][dst] = tm; rem &= ~(1ULL << dst); m &= (m - 1); } } } return latest; } vector>> precomputeSqBest(const vector &sqFlights) const { vector>> sqBest(TARGET_CNT, vector>(N, vector(N, NEG_INF))); for(int k = 0; k < TARGET_CNT; ++k) { int target = TARGET_START + TARGET_STEP * k; auto byStart = buildByStart(sqFlights, target); sqBest[k] = latestMatrixForTarget(byStart, target); } return sqBest; } vector>> precomputeAllLatest(const vector &flights) const { vector> allByStart(MAX_SLOT + 1); for(const auto &f : flights) { if(0 <= f.s && f.s <= MAX_SLOT && 0 <= f.t && f.t <= MAX_SLOT) allByStart[f.s].push_back(f); } vector>> allLatest(MAX_SLOT + 1, vector>(N, vector(N, NEG_INF))); for(int deadline = 0; deadline <= MAX_SLOT; ++deadline) { vector> reach(deadline + 1, vector(N, 0ULL)); for(int c = 0; c < N; ++c) reach[deadline][c] = (1ULL << c); for(int tm = deadline - 1; tm >= 0; --tm) { for(int c = 0; c < N; ++c) reach[tm][c] = reach[tm + 1][c]; for(const auto &f : allByStart[tm]) { if(f.t <= deadline) reach[tm][f.a] |= reach[f.t][f.b]; } } for(int src = 0; src < N; ++src) { uint64_t rem = allMask; for(int tm = deadline; tm >= 0 && rem; --tm) { uint64_t m = reach[tm][src] & rem; while(m) { int dst = __builtin_ctzll(m); allLatest[deadline][src][dst] = tm; rem &= ~(1ULL << dst); m &= (m - 1); } } } } return allLatest; } double score( const vector &ciFlights, const vector &demands) const { long double vSq = 0.0L, vCi = 0.0L; for(int k = 0; k < TARGET_CNT; ++k) { int target = TARGET_START + TARGET_STEP * k; auto byStart = buildByStart(ciFlights, target); auto latest = latestMatrixForTarget(byStart, target); for(const auto &d : demands) { if(d.sq[k] < latest[d.src][d.dst]) vCi += d.w; else vSq += d.w; } } long double den = vSq + vCi; if(den <= 0.0L) return 0.0; return (double)(vCi / den); } }; PlanePlan buildCyclicPlan( const vector &cycle, int offset, const vector> &dur) { PlanePlan p; if(cycle.empty()) return p; p.route.push_back(cycle[0]); p.offset = offset; int tm = offset; int cur = cycle[0]; int idx = 1 % (int)cycle.size(); while(true) { int nxt = cycle[idx]; if(nxt == cur) break; int nt = tm + dur[cur][nxt]; if(nt > MAX_SLOT) break; p.route.push_back(nxt); tm = nt; cur = nxt; idx = (idx + 1) % (int)cycle.size(); } p.duration = tm - offset; normalizePlane(p, dur); return p; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); 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 sqFlights(M); for(int i = 0; i < M; ++i) { int a, b; string ss, tt; cin >> a >> ss >> b >> tt; --a; --b; sqFlights[i] = {a, b, parseTimeToSlot(ss), parseTimeToSlot(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) dur[i][j] = calcDurationSlot(cities[i], cities[j]); } vector> pairWeight(N, vector(N, 0.0L)); double threshold = 0.25 * R; for(int i = 0; i < N; ++i) { for(int j = 0; j < N; ++j) { double dx = double(cities[i].x) - double(cities[j].x); double dy = double(cities[i].y) - double(cities[j].y); double d = sqrt(dx * dx + dy * dy); if(d + 1e-12 >= threshold) { pairWeight[i][j] = (long double)cities[i].w * (long double)cities[j].w; } } } ScoreEvaluator evaluator(N); auto sqBest = evaluator.precomputeSqBest(sqFlights); // [k][src][dst] vector demands; demands.reserve(N * N); for(int src = 0; src < N; ++src) { for(int dst = 0; dst < N; ++dst) { if(pairWeight[src][dst] == 0.0L) continue; DemandTerm d; d.src = src; d.dst = dst; d.w = pairWeight[src][dst]; for(int k = 0; k < TARGET_CNT; ++k) d.sq[k] = sqBest[k][src][dst]; demands.push_back(d); } } vector> demandId(N, vector(N, -1)); for(int i = 0; i < (int)demands.size(); ++i) demandId[demands[i].src][demands[i].dst] = i; vector cityScore(N, 0.0L); for(int i = 0; i < N; ++i) { long double s = (long double)cities[i].w * 1e6L; for(int j = 0; j < N; ++j) s += pairWeight[i][j] + pairWeight[j][i]; cityScore[i] = max((long double)1.0, s); } vector cityOrd(N); iota(cityOrd.begin(), cityOrd.end(), 0); sort(cityOrd.begin(), cityOrd.end(), [&](int a, int b) { return cityScore[a] > cityScore[b]; }); long double totalDen = 0.0L; for(const auto &d : demands) totalDen += d.w; totalDen *= (long double)TARGET_CNT; double bestScoreAll = -1.0; int bestTrial = -1; vector bestPlans; vector bestFlights; auto baseLatestAll = evaluator.precomputeAllLatest({}); mt19937_64 rng(123456789ULL); const double TL = 0.9; auto begin = chrono::steady_clock::now(); int trial = 0; while(true) { double elapsed = chrono::duration(chrono::steady_clock::now() - begin).count(); if(trial > 0 && elapsed >= TL) break; vector plans(K); vector> routes(K); vector headCity(K), headTime(K), legCount(K, 0); vector seedOrder = cityOrd; int mode = trial % 4; if(mode == 0) { int shift = (trial * 7) % N; rotate(seedOrder.begin(), seedOrder.begin() + shift, seedOrder.end()); } else if(mode == 1) { reverse(seedOrder.begin(), seedOrder.end()); int shift = (trial * 5) % N; rotate(seedOrder.begin(), seedOrder.begin() + shift, seedOrder.end()); } else if(mode == 2) { int top = min(N, max(12, K * 2)); shuffle(seedOrder.begin(), seedOrder.begin() + top, rng); int shift = (int)(rng() % N); rotate(seedOrder.begin(), seedOrder.begin() + shift, seedOrder.end()); } else { int top = min(N, max(20, K * 3)); shuffle(seedOrder.begin(), seedOrder.begin() + top, rng); int rest = min(N, top + 10); if(top < rest) shuffle(seedOrder.begin() + top, seedOrder.begin() + rest, rng); int shift = (int)(rng() % N); rotate(seedOrder.begin(), seedOrder.begin() + shift, seedOrder.end()); } for(int p = 0; p < K; ++p) { int c = seedOrder[p % N]; routes[p].push_back(c); headCity[p] = c; headTime[p] = MAX_SLOT; } vector>> latestAll = baseLatestAll; long double currentCi = 0.0L; double currentScore = 0.0; auto calcDeltaCi = [&](int a, int b, int dep, int arr) -> long double { long double deltaCi = 0.0L; const auto &depMat = latestAll[dep]; array preBySrc{}; array activeSrc{}; int activeSrcCnt = 0; for(int src = 0; src < N; ++src) if((preBySrc[src] = depMat[src][a]) != NEG_INF) activeSrc[activeSrcCnt++] = src; if(activeSrcCnt == 0) return 0.0L; int startK = 0; if(arr > TARGET_START) { startK = (arr - TARGET_START + TARGET_STEP - 1) / TARGET_STEP; if(startK < 0) startK = 0; if(startK > TARGET_CNT) startK = TARGET_CNT; } for(int k = startK; k < TARGET_CNT; ++k) { int target = TARGET_START + TARGET_STEP * k; const auto &targetMat = latestAll[target]; array okDst{}; int activeDstCnt = 0; for(int dst = 0; dst < N; ++dst) { if(targetMat[b][dst] >= arr) { okDst[activeDstCnt++] = dst; } } if(activeDstCnt == 0) continue; for(int si = 0; si < activeSrcCnt; ++si) { int src = activeSrc[si]; int pre = preBySrc[src]; for(int di = 0; di < activeDstCnt; ++di) { int dst = okDst[di]; int idx2 = demandId[src][dst]; if(idx2 < 0) continue; const auto &d = demands[idx2]; int oldCi = targetMat[src][dst]; if(pre <= oldCi) continue; if(d.sq[k] < pre && !(d.sq[k] < oldCi)) deltaCi += d.w; } } } return deltaCi; }; auto applyFlightToLatestAll = [&](int a, int b, int dep, int arr) { const auto &depMat = latestAll[dep]; for(int target = arr; target <= MAX_SLOT; ++target) { auto &targetMat = latestAll[target]; array dstList{}; int dstCnt = 0; for(int dst = 0; dst < N; ++dst) { if(targetMat[b][dst] >= arr) dstList[dstCnt++] = dst; } if(dstCnt == 0) continue; for(int src = 0; src < N; ++src) { int pre = depMat[src][a]; if(pre == NEG_INF) continue; for(int i = 0; i < dstCnt; ++i) { int dst = dstList[i]; if(pre > targetMat[src][dst]) targetMat[src][dst] = pre; } } } }; int maxLegPerPlane = 14; int maxTotalOps = K * maxLegPerPlane; for(int op = 0; op < maxTotalOps; ++op) { vector> ops; // plane, from, dep, arr ops.reserve(K * N); for(int p = 0; p < K; ++p) { if(legCount[p] >= maxLegPerPlane) continue; int b = headCity[p]; int arr = headTime[p]; for(int a = 0; a < N; ++a) { if(a == b) continue; int dep = arr - dur[a][b]; if(dep < 0) continue; ops.emplace_back(p, a, dep, arr); } } if(ops.empty()) break; double bestScore = currentScore; long double bestDeltaCi = 0.0L; int bestPlane = -1, bestFrom = -1, bestDep = -1, bestArr = -1; for(const auto &[p, a, dep, arr] : ops) { int b = headCity[p]; long double deltaCi = calcDeltaCi(a, b, dep, arr); double s = (totalDen > 0.0L ? (double)((currentCi + deltaCi) / totalDen) : 0.0); if(s > bestScore || (s == bestScore && deltaCi > bestDeltaCi)) { bestScore = s; bestDeltaCi = deltaCi; bestPlane = p; bestFrom = a; bestDep = dep; bestArr = arr; } } if(bestPlane < 0) { break; } int b = headCity[bestPlane]; routes[bestPlane].insert(routes[bestPlane].begin(), bestFrom); headCity[bestPlane] = bestFrom; headTime[bestPlane] = bestDep; legCount[bestPlane]++; applyFlightToLatestAll(bestFrom, b, bestDep, bestArr); currentCi += bestDeltaCi; currentScore = (totalDen > 0.0L ? (double)(currentCi / totalDen) : 0.0); } for(int p = 0; p < K; ++p) { PlanePlan pl; pl.route = routes[p]; pl.offset = headTime[p]; normalizePlane(pl, dur); plans[p] = pl; } vector finalFlights = flattenPlans(plans, dur); double finalScore = evaluator.score(finalFlights, demands); cerr << fixed << setprecision(12) << "trial=" << trial << " score=" << finalScore << " flights=" << finalFlights.size() << '\n'; if(finalScore > bestScoreAll) { bestScoreAll = finalScore; bestTrial = trial; bestPlans = plans; bestFlights = finalFlights; } trial++; } vector plans = bestPlans; vector finalFlights = bestFlights; double finalScore = bestScoreAll; vector flownCity(N, 0); for(const auto &f : finalFlights) { flownCity[f.a] = 1; flownCity[f.b] = 1; } for(int i = 0; i < K; ++i) { const auto &p = plans[i]; cout << max(0, (int)p.route.size() - 1) << '\n'; int tm = p.offset; for(int j = 1; j < (int)p.route.size(); ++j) { int a = p.route[j - 1], b = p.route[j]; int nt = tm + dur[a][b]; cout << (a + 1) << ' ' << slotToTime(tm) << ' ' << (b + 1) << ' ' << slotToTime(nt) << '\n'; tm = nt; } } cerr << fixed << setprecision(12) << "best_trial=" << bestTrial << ' ' << "score=" << finalScore << " unique_cities=" << count(flownCity.begin(), flownCity.end(), 1) << " flights=" << finalFlights.size() << '\n'; return 0; }