結果

問題 No.5023 Airlines Optimization
コンテスト
ユーザー twins_fuyu
提出日時 2026-02-25 23:57:48
言語 C++17
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++17 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
AC  
実行時間 146 ms / 1,000 ms
コード長 9,995 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 4,786 ms
コンパイル使用メモリ 389,404 KB
実行使用メモリ 7,848 KB
スコア 39,656,609
最終ジャッジ日時 2026-02-25 23:58:28
合計ジャッジ時間 19,411 ms
ジャッジサーバーID
(参考情報)
judge3 / judge4
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other AC * 100
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#include "immintrin.h"
using namespace std;
#define rep1(a) for (int _ = 0; _ < (a); ++_)
#define rep2(i, a) for (int i = 0; i < (a); ++i)
#define rep3(i, a, b) for (int i = a; i < (b); ++i)
#define rrep1(a) for (int i = (a) - 1; i >= 0; --i)
#define rrep2(i, a) for (int i = (a) - 1; i >= 0; --i)
#define rrep3(i, a, b) for (int i = (b) - 1; i >= (a); --i)
#define overload3(a, b, c, d, ...) d
#define rep(...) overload3(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)
#define rrep(...) overload3(__VA_ARGS__, rrep3, rrep2, rrep1)(__VA_ARGS__)
#define in(i, vec) for (auto i : (vec))
template <class T>
using pqueue = priority_queue<T, vector<T>>; // 大きい順
template <class T>
using pqueue_g = priority_queue<T, vector<T>, greater<T>>; // 小さい順

namespace library
{
    class xorshift128plus
    {
    private:
        uint64_t s[2];

    public:
        using result_type = uint64_t;

        xorshift128plus(uint64_t seed = 1)
        {
            seed_gen(seed);
        }

        void seed(uint64_t seed_val)
        {
            seed_gen(seed_val);
        }

        static constexpr result_type min()
        {
            return std::numeric_limits<result_type>::min();
        }

        static constexpr result_type max()
        {
            return std::numeric_limits<result_type>::max();
        }

        result_type operator()()
        {
            uint64_t s1 = s[0];
            uint64_t s0 = s[1];
            s[0] = s0;
            s1 ^= s1 << 23;
            s[1] = s1 ^ s0 ^ (s1 >> 17) ^ (s0 >> 26);
            return s[1] + s0;
        }

    private:
        void seed_gen(uint64_t seed_val)
        {
            // SplitMix64 で状態2個を初期化
            s[0] = splitmix64(seed_val);
            s[1] = splitmix64(s[0]);
        }

        static uint64_t splitmix64(uint64_t &x)
        {
            x += 0x9E3779B97F4A7C15ULL;
            uint64_t z = x;
            z = (z ^ (z >> 30)) * 0xBF58476D1CE4E5B9ULL;
            z = (z ^ (z >> 27)) * 0x94D049BB133111EBULL;
            return z ^ (z >> 31);
        }
    };

    struct Timer
    {
        chrono::steady_clock::time_point start;
        Timer() : start(chrono::steady_clock::now()) {}
        double elapse()
        {
            return chrono::duration<double>(chrono::steady_clock::now() - start).count();
        }
        bool over(double t)
        {
            return elapse() > t;
        }
        bool operator()(double t)
        {
            return elapse() < t;
        }
    };

    void fast_io()
    {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    }

    uint64_t exp_table[2001];

    bool init_exp_table(){
        for(int i=0;i<=2000;++i){
            exp_table[i]=numeric_limits<uint64_t>::max()*exp(double(-i)/100.0);
        }
        return true;
    }
    bool exp_table_initialized = init_exp_table();

    uint64_t sa_exp(double diff, double temperature){
        if(temperature==0) return 0;
        else if (diff>=0) return numeric_limits<uint64_t>::max();
        int index = int(-diff * 100.0 / temperature);
        if(index>2000) return 0;
        return exp_table[index];
    }

} // namespace library

uniform_real_distribution<double> rnd(0.0, 1.0);
normal_distribution<double> randn(0.0, 1.0);
library::xorshift128plus rng(12345);
library::Timer timer;
double TL = 1.9;

constexpr int N = 47;
constexpr int M = 400;
constexpr int R = 1000;
long long W[N];
int DIST[N][N];
bool near[N][N];

struct QueryResult{
    int result[N][N][21];
    QueryResult(){
        rep(i,N)rep(j,N)rep(k,21)result[i][j][k] = -1;
    }
};

struct State{
    vector<tuple<int,int,int>> G[N]; // goal -> (start, start_time, goal_time)

    void sort_g(){
        rep(i,N){
            sort(G[i].begin(), G[i].end(), [](const auto& a, const auto& b){
                return get<2>(a) < get<2>(b);
            });
        }
    }

    void query_one(int goal, int goal_time, QueryResult& res){
        // 逆順でDijkstra
        bool vis[N] = {};
        pqueue<tuple<int,int>> pq; // (time, node)
        for(auto [prv, st, gt]:G[goal]){
            if(gt > goal_time) continue;
            pq.emplace(st, prv);
        }
        while (!pq.empty()){
            auto [cur_time, node] = pq.top(); pq.pop();
            if(vis[node]) continue;
            vis[node] = true;
            res.result[node][goal][(goal_time - 300) / 30] = cur_time;
            for(auto [prv, st, gt]:G[node]){
                if(gt > cur_time) continue;
                if(vis[prv]) continue;
                pq.emplace(st, prv);
            }
        }
    }

    QueryResult query_all(){
        QueryResult res;
        const int query_start_time = 300; // 11:00
        sort_g();
        rep(goal,N){
            for(int goal_time = query_start_time; goal_time <= 900; goal_time += 30){
                query_one(goal, goal_time, res);
            }
        }
        return res;
    }
};

State SQUARE;


constexpr int K = 25;

int get_time(int d_squared){
    double d = sqrt(d_squared);
    long long m = max(0.0 ,(3*d) / 200 - 1);
    long long d_squared_ll = d_squared;
    while ((200*m)*(200*m) < 9*d_squared_ll) {
        m += 1;
    }
    return 40 + 5*m;
}

int parse(const string& s){
    // s 06:00 ~ 21:00
    int hour = stoi(s.substr(0, 2));
    int minute = stoi(s.substr(3, 2));
    return (hour - 6) * 60 + minute;
}
string format_time(int t){
    int hour = 6 + t / 60;
    int minute = t % 60;
    string res;
    if(hour < 10) res += "0";
    res += to_string(hour) + ":";
    if(minute < 10) res += "0";
    res += to_string(minute);
    return res;
}

void get_input(){
    int n,r; cin>>n>>r;
    assert(n==N && r==R);
    pair<int,int> xy[N];
    rep(i,N){
        int x,y,w; cin>>x>>y>>w;
        xy[i] = {x,y};
        W[i] = w;
    }
    rep(i,N)DIST[i][i] = 0, near[i][i] = true;
    rep(i,N)rep(j,i+1,N){
        int dx = xy[i].first - xy[j].first;
        int dy = xy[i].second - xy[j].second;
        DIST[i][j] = get_time(dx*dx + dy*dy);
        DIST[j][i] = DIST[i][j];
        near[i][j] = (16*(dx*dx + dy*dy) < R*R) ? true : false;
    }
    int m; cin>>m;
    assert(m==M);
    rep(i,M){
        int a,b;
        string s,t;
        cin >> a >> s >> b >> t;
        a--; b--;
        SQUARE.G[b].emplace_back(a, parse(s), parse(t));
    }
    SQUARE.sort_g();
}

double get_score(State& state, const QueryResult& opponent_query){
    QueryResult player_query = state.query_all();
    long long w_player = 0, w_opponent = 0;
    rep(i,N)rep(j,N)if(!near[i][j])rep(k,21){
        int player_time = player_query.result[i][j][k];
        int opponent_time = opponent_query.result[i][j][k];
        if(player_time > opponent_time) w_player += W[i]*W[j];
        else w_opponent += W[i]*W[j];
    }
    cerr << "Player: " << w_player/1e10 << ", Opponent: " << w_opponent/1e10 << endl;
    return w_player / double(w_player + w_opponent);
}

struct AirLine{
    int start;
    vector<int> goals;
    vector<int> goal_times;

    AirLine(int start):start(start){}

    void add_goal(int goal, int goal_time){
        int last_goal_time = goal_times.empty() ? 0 : goal_times.back();
        int start_time = last_goal_time + DIST[start][goal];
        assert(last_goal_time <= start_time);
        goals.push_back(goal);
        goal_times.push_back(goal_time);
    }

    State get_state() const {
        State state;
        int cur_start = start;
        for(size_t i=0;i<goals.size();++i){
            int goal = goals[i];
            int goal_time = goal_times[i];
            int start_time = goal_time - DIST[cur_start][goal];
            state.G[goal].emplace_back(cur_start, start_time, goal_time);
            cur_start = goal;
        }
        return state;
    }
};

vector<AirLine> get_airlines(int center){
    int target = 0;
    vector<AirLine> airlines;
    rep(i,K){
        if(target==center) target++;
        int cur_time = 0;
        airlines.emplace_back(target);
        int dist = DIST[0][target];
        rep(itr,100){
            int nxt_time = cur_time + dist;
            if(nxt_time > 900) break;
            int to = itr%2 ? target : 0;
            airlines[i].add_goal(to, nxt_time);
            cur_time = nxt_time; 
        }
        target++;
    }
    return airlines;
}

State get_state_from_airlines(const vector<AirLine>& airlines){
    State state;
    for(const auto& airline: airlines){
        int start = airline.start;
        for(size_t i=0;i<airline.goals.size();++i){
            int goal = airline.goals[i];
            int goal_time = airline.goal_times[i];
            int start_time = goal_time - DIST[start][goal];
            state.G[goal].emplace_back(start, start_time, goal_time);
            start = goal;
        }
    }
    return state;
}

void output(const vector<AirLine>& airlines){
    for(const auto& airline: airlines){
        cout << airline.goals.size() << endl;
        rep(i,airline.goals.size()){
            int start = (i == 0) ? airline.start : airline.goals[i-1];
            int goal = airline.goals[i];
            int goal_time = airline.goal_times[i];
            int start_time = goal_time - DIST[start][goal];
            cout << start + 1 << " " << format_time(start_time) << " " << goal + 1 << " " << format_time(goal_time) << endl;
        }
    }
}

int main(){
    library::fast_io();
    get_input();
    QueryResult opponent_query = SQUARE.query_all();

    vector<AirLine> best_airlines;
    double best_score = -1e18;
    rep(center,N){
        auto airlines = get_airlines(center);
        State state = get_state_from_airlines(airlines);
        double score = get_score(state, opponent_query);
        if(score > best_score){
            best_score = score;
            best_airlines = airlines;
        }
        cerr << "Center: " << center << ", Score: " << score << endl;
    }
    cerr << "Best Score: " << best_score << endl;

    output(best_airlines);
    
    return 0;
}
0