結果

問題 No.5023 Airlines Optimization
コンテスト
ユーザー shogo314
提出日時 2026-02-25 21:36:56
言語 C++23
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 909 ms / 1,000 ms
コード長 6,661 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 2,639 ms
コンパイル使用メモリ 225,268 KB
実行使用メモリ 7,848 KB
スコア 36,632,416
最終ジャッジ日時 2026-02-25 21:38:36
合計ジャッジ時間 99,384 ms
ジャッジサーバーID
(参考情報)
judge2 / judge6
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 100
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <sstream>
#include <chrono>

using namespace std;

const int MIN_TIME = 6 * 60;
const int MAX_TIME = 21 * 60;

struct City { int id, x, y; long long w; };
struct Flight { int from, to, s, t; };

int time_to_int(string s) { return stoi(s.substr(0, 2)) * 60 + stoi(s.substr(3, 2)); }
string int_to_time(int t) {
    ostringstream oss;
    oss << setfill('0') << setw(2) << (t / 60) << ":" << setw(2) << (t % 60);
    return oss.str();
}

int get_travel_time(const City& a, const City& b) {
    double d = sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2));
    int duration = ceil((60.0 * d / 800.0) + 40.0);
    return ((duration + 4) / 5) * 5;
}

int ssq[48][48][21];
int current_start_city[25];
vector<Flight> schedules[25];

// 自社便全体の最遅出発時刻を管理 [from][to][target_t_idx]
int sci[48][48][21];

// 自社便のネットワークを解析して sci テーブルを更新する関数
void update_sci(int N, int K) {
    for (int i = 1; i <= N; ++i)
        for (int j = 1; j <= N; ++j)
            for (int t = 0; t < 21; ++t) sci[i][j][t] = -1;

    for (int k = 0; k < K; ++k) {
        for (auto& f : schedules[k]) {
            for (int t_idx = 0; t_idx < 21; ++t_idx) {
                int target_t = 660 + (t_idx * 30);
                if (f.t <= target_t) sci[f.from][f.to][t_idx] = max(sci[f.from][f.to][t_idx], f.s);
            }
        }
    }

    // ワーシャルフロイドで乗り継ぎを考慮 (自社便ネットワークの伝播)
    for (int t_idx = 0; t_idx < 21; ++t_idx) {
        for (int mid = 1; mid <= N; ++mid) {
            for (int i = 1; i <= N; ++i) {
                if (sci[i][mid][t_idx] == -1) continue;
                for (int j = 1; j <= N; ++j) {
                    if (sci[mid][j][t_idx] != -1 && sci[mid][j][t_idx] >= -1/*本来は到着時刻との比較が必要だが簡略化*/) {
                        // 実際には f1.t <= f2.s である必要があるため、
                        // 簡易的に直接便の組み合わせによる最遅出発を評価
                        // ここを精密にするほどスコアが上がる
                    }
                }
            }
        }
    }
}

// 評価関数:現在の全スケジュールにおけるシェア合計スコアを計算
long long calculate_total_score(int N, const vector<City>& cities) {
    long long total = 0;
    for (int i = 1; i <= N; ++i) {
        for (int j = 1; j <= N; ++j) {
            if (i == j) continue;
            for (int t = 0; t < 21; ++t) {
                if (sci[i][j][t] > ssq[i][j][t]) {
                    total += cities[i-1].w * cities[j-1].w;
                }
            }
        }
    }
    return total;
}

// 単一機体を「今の他機の状況」に合わせて最適化
vector<Flight> rebuild_schedule_network(int k, int N, const vector<City>& cities) {
    vector<Flight> sch;
    int cur_city = current_start_city[k];
    int cur_time = MIN_TIME;
    
    while (cur_time < MAX_TIME) {
        int best_to = -1, best_s = -1, best_dur = -1;
        double max_val = -1e18;

        for (int wait = 0; wait <= 60; wait += 10) { // 高速化のためステップを広げる
            int st = cur_time + wait;
            if (st > MAX_TIME - 45) break;
            for (int nxt = 1; nxt <= N; ++nxt) {
                if (cur_city == nxt) continue;
                int dur = get_travel_time(cities[cur_city-1], cities[nxt-1]);
                if (st + dur > MAX_TIME) continue;

                long long potential_gain = 0;
                for (int t = 0; t < 21; ++t) {
                    if (st + dur <= 660 + t * 30) {
                        // 他の機体がカバーしていない、かつSQに勝てるなら大きな加点
                        if (sci[cur_city][nxt][t] <= ssq[cur_city][nxt][t] && st > ssq[cur_city][nxt][t]) {
                            potential_gain += cities[cur_city-1].w * cities[nxt-1].w;
                        }
                    }
                }
                
                double evaluation = (double)potential_gain;
                // ハブ・ネットワーク維持ボーナス
                if (nxt <= 5) evaluation += (double)cities[nxt-1].w / 5e5;
                evaluation -= wait * 0.2;

                if (evaluation > max_val) {
                    max_val = evaluation; best_to = nxt; best_s = st; best_dur = dur;
                }
            }
        }
        if (best_to != -1 && max_val > -1e9) {
            sch.push_back({cur_city, best_to, best_s, best_s + best_dur});
            cur_city = best_to; cur_time = best_s + best_dur;
        } else break;
    }
    return sch;
}

int main() {
    auto start_time = chrono::system_clock::now();
    ios::sync_with_stdio(false); cin.tie(nullptr);

    int N, R; cin >> N >> R;
    vector<City> cities(N);
    for (int i = 0; i < N; ++i) cin >> cities[i].x >> cities[i].y >> cities[i].w;
    int M; cin >> M;
    for (int i = 1; i <= N; ++i) for (int j = 1; j <= N; ++j) for (int t = 0; t < 21; ++t) ssq[i][j][t] = -1;
    for (int i = 0; i < M; ++i) {
        int a, b; string s, t; cin >> a >> s >> b >> t;
        int si = time_to_int(s), ti = time_to_int(t);
        for (int k = 0; k < 21; ++k) if (ti <= 660 + k * 30) ssq[a][b][k] = max(ssq[a][b][k], si);
    }
    int K; cin >> K;

    for (int k = 0; k < K; ++k) current_start_city[k] = (k % 5) + 1;

    // 初期解
    for (int k = 0; k < K; ++k) {
        schedules[k] = rebuild_schedule_network(k, N, cities);
        update_sci(N, K);
    }

    int iter = 0;
    while (true) {
        iter++;
        if (iter % 5 == 0) {
            auto now = chrono::system_clock::now();
            if (chrono::duration_cast<chrono::milliseconds>(now - start_time).count() > 900) break;
        }

        int k = rand() % K;
        vector<Flight> old_sch = schedules[k];
        
        // 仮に空にして再構築
        schedules[k].clear();
        update_sci(N, K);
        
        vector<Flight> new_sch = rebuild_schedule_network(k, N, cities);
        schedules[k] = new_sch;
        update_sci(N, K);
        
        // 本来は全体の真のシェアを計算して比較すべきだが、
        // 貪欲な再構築を繰り返すだけでもネットワークの整合性は向上する
    }

    for (int k = 0; k < K; ++k) {
        cout << schedules[k].size() << "\n";
        for (auto& f : schedules[k]) cout << f.from << " " << int_to_time(f.s) << " " << f.to << " " << int_to_time(f.t) << "\n";
    }
    return 0;
}
0