結果

問題 No.5023 Airlines Optimization
コンテスト
ユーザー tomerun
提出日時 2026-02-26 00:25:11
言語 Rust
(1.93.0 + proconio + num + itertools)
コンパイル:
/usr/bin/rustc_custom
実行:
./target/release/main
結果
RE  
実行時間 -
コード長 14,591 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 13,629 ms
コンパイル使用メモリ 373,544 KB
実行使用メモリ 7,968 KB
スコア 0
最終ジャッジ日時 2026-02-26 00:25:31
合計ジャッジ時間 17,257 ms
ジャッジサーバーID
(参考情報)
judge2 / judge6
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other RE * 100
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

// #![allow(unused_imports)]
// #![allow(dead_code)]
// #![allow(non_snake_case)]
use std::env;
use std::io::{self, BufRead, BufReader, Read, Stdin};
use std::mem;
use std::str::FromStr;
use std::string::String;
use std::time;

const TIMELIMIT: u64 = 950;
const INF: usize = 1 << 28;
const N: usize = 20;
const R: usize = 1000;
const M: usize = 400;
const K: usize = 25;

#[derive(Debug)]
pub struct Scanner<R> {
    reader: BufReader<R>,
}

fn scanner() -> Scanner<Stdin> {
    Scanner::new(io::stdin())
}

impl<R: io::Read> Scanner<R> {
    pub fn new(read: R) -> Scanner<R> {
        Scanner { reader: BufReader::new(read) }
    }

    pub fn next_str(&mut self) -> Option<String> {
        let mut buf = [0; 1];
        let size = self.reader.read(&mut buf).unwrap();
        if size == 0 {
            None
        } else {
            self.skip_whitespace(&mut buf)?;
            let mut v = vec![buf[0]];
            loop {
                let size = self.reader.read(&mut buf).unwrap();
                if size == 0 || buf[0].is_ascii_whitespace() {
                    break;
                }
                v.push(buf[0]);
            }
            Some(String::from_utf8(v).unwrap())
        }
    }

    pub fn next_line(&mut self) -> String {
        let mut line = String::new();
        self.reader.read_line(&mut line).unwrap();
        if let Some(s) = line.strip_suffix("\n") { s.to_string() } else { line }
    }

    pub fn next_as<S: FromStr>(&mut self) -> Option<S> {
        let s = self.next_str()?;
        S::from_str(&s).ok()
    }

    pub fn str(&mut self) -> String {
        self.next_str().unwrap()
    }

    pub fn i32(&mut self) -> i32 {
        self.next_as::<i32>().unwrap()
    }

    pub fn u32(&mut self) -> u32 {
        self.next_as::<u32>().unwrap()
    }

    pub fn u64(&mut self) -> u64 {
        self.next_as::<u64>().unwrap()
    }

    pub fn usize(&mut self) -> usize {
        self.next_as::<usize>().unwrap()
    }

    fn skip_whitespace(&mut self, mut buf: &mut [u8]) -> Option<u8> {
        loop {
            if !buf[0].is_ascii_whitespace() {
                return Some(buf[0]);
            }
            let size = self.reader.read(&mut buf).unwrap();
            if size == 0 {
                return None;
            }
        }
    }
}

struct XorShift32 {
    state: u32,
}

impl XorShift32 {
    fn from_seed(seed: u32) -> Self {
        let initial_state = if seed == 0 { 1 } else { seed };
        XorShift32 { state: initial_state }
    }

    fn next_u32(&mut self) -> u32 {
        let mut x = self.state;
        x ^= x << 13;
        x ^= x >> 17;
        x ^= x << 5;
        self.state = x;
        x
    }

    fn next_f64(&mut self) -> f64 {
        self.next_u32() as f64 / (u32::MAX as f64 + 1.0)
    }
}

#[derive(Debug)]
struct Timer {
    start_time: time::Instant,
    limit: time::Instant,
}

impl Timer {
    fn new(tl: u64) -> Timer {
        let start_time = time::Instant::now();
        Timer { start_time, limit: start_time + time::Duration::from_millis(tl) }
    }

    fn elapsed(&self) -> u64 {
        self.start_time.elapsed().as_millis() as u64
    }

    fn tl(&self) -> u64 {
        (self.limit - self.start_time).as_millis() as u64
    }
}

fn time_to_str(t: usize) -> String {
    let h = t / 12 + 6;
    let m = (t % 12) * 5;
    format!("{:02}:{:02}", h, m)
}

struct Input {
    ws: [u64; N],
    start_at: [[[usize; N]; N]; 21],
    dist: [[usize; N]; N],
    far: [[bool; N]; N],
}

impl Input {
    fn new() -> Input {
        let mut sc = scanner();
        sc.next_line();
        let mut pos = [Pos::new(0, 0); N];
        let mut ws = [0; N];
        for i in 0..N {
            let y = sc.i32() as usize;
            let x = sc.i32() as usize;
            let w = sc.u64();
            pos[i] = Pos::new(y, x);
            ws[i] = w;
        }
        let mut dist = [[0; N]; N];
        let mut far = [[false; N]; N];
        for i in 0..N {
            for j in 0..N {
                let d2 = pos[i].dist2(&pos[j]);
                if d2 >= (R / 4) * (R / 4) {
                    far[i][j] = true;
                }
                dist[i][j] = (((d2 as f64).sqrt() * 60.0 / 800.0 + 40.0) / 5.0).ceil() as usize;
            }
            dist[i][i] = INF;
        }
        sc.usize();
        let mut flight = vec![vec![]; N];
        for _ in 0..M {
            let a = sc.usize() - 1;
            let ss = sc.str();
            let b = sc.usize() - 1;
            let ts = sc.str();
            let s = ((ss[0..2].parse::<usize>().unwrap() - 6) * 60 + ss[3..5].parse::<usize>().unwrap()) / 5;
            let t = ((ts[0..2].parse::<usize>().unwrap() - 6) * 60 + ts[3..5].parse::<usize>().unwrap()) / 5;
            flight[b].push((a, s, t));
            assert!(t - s == dist[a][b]);
        }
        let mut start_at = [[[INF; N]; N]; 21];
        for i in 0..N {
            let mut time = [INF; N];
            for st in 0..=20 {
                time[i] = st * 6 + 60;
                let mut heap = std::collections::BinaryHeap::new();
                heap.push((time[i], i));
                while let Some((now, u)) = heap.pop() {
                    if time[u] < now {
                        continue;
                    }
                    for &(v, s, t) in &flight[u] {
                        if t <= now && (time[v] == INF || s > time[v]) {
                            time[v] = s;
                            heap.push((s, v));
                        }
                    }
                }
                for j in 0..N {
                    start_at[st][j][i] = time[j];
                    // eprintln!(
                    //     "{:?}->{:?} {} {}",
                    //     j,
                    //     i,
                    //     time_to_str(st * 6 + 60),
                    //     if time[j] == INF { "-".to_string() } else { time_to_str(time[j]) }
                    // );
                }
            }
        }

        Input { ws, start_at, dist, far }
    }
}

#[derive(Debug, Clone, Copy)]
struct Pos {
    y: usize,
    x: usize,
}

impl Pos {
    fn new(y: usize, x: usize) -> Pos {
        Pos { y, x }
    }

    fn dist2(&self, other: &Pos) -> usize {
        let dy = self.y as i32 - other.y as i32;
        let dx = self.x as i32 - other.x as i32;
        (dy * dy + dx * dx) as usize
    }
}

#[derive(Debug, Clone, Copy)]
struct Flight {
    a: usize,
    b: usize,
    s: usize,
    t: usize,
}

impl Flight {
    fn new(a: usize, b: usize, s: usize, t: usize) -> Flight {
        Flight { a, b, s, t }
    }
}

#[derive(Debug, Clone)]
struct Result {
    flights: Vec<Vec<Flight>>,
    score: f64,
}

impl Result {
    fn new(flights: Vec<Vec<Flight>>, score: f64) -> Result {
        Result { flights, score }
    }

    fn new_empty() -> Result {
        Result { flights: vec![vec![]; K], score: 0.0 }
    }

    fn output(&self) {
        for i in 0..K {
            println!("{}", self.flights[i].len());
            for f in &self.flights[i] {
                println!("{} {} {} {}", f.a + 1, time_to_str(f.s), f.b + 1, time_to_str(f.t));
            }
        }
    }
}

struct Solver {
    input: Input,
    timer: Timer,
    rng: XorShift32,
    start_at: [[[usize; N]; N]; 21],
}

impl Solver {
    fn new(input: Input) -> Solver {
        let tl = env::var("TL").map_or(TIMELIMIT, |v| v.parse().unwrap());
        let timer = Timer::new(tl);
        let rng = XorShift32::from_seed(2);
        let start_at = [[[INF; N]; N]; 21];
        Solver { input, timer, rng, start_at }
    }

    fn calc_score(&mut self, flights: &[Vec<Flight>]) -> (f64, [[[usize; N]; N]; 21]) {
        let mut direct = vec![vec![]; N];
        for fs in flights {
            for f in fs {
                direct[f.b].push((f.a, f.s, f.t));
            }
        }
        for i in 0..self.start_at.len() {
            for j in 0..N {
                self.start_at[i][j].fill(INF);
            }
        }
        let mut start_at = [[[INF; N]; N]; 21];
        for i in 0..N {
            let mut time = [INF; N];
            for st in 0..=20 {
                time[i] = st * 6 + 60;
                let mut heap = std::collections::BinaryHeap::new();
                heap.push((time[i], i));
                while let Some((now, u)) = heap.pop() {
                    if time[u] < now {
                        continue;
                    }
                    for &(v, s, t) in &direct[u] {
                        if t <= now && (time[v] == INF || s > time[v]) {
                            time[v] = s;
                            heap.push((s, v));
                        }
                    }
                }
                for j in 0..N {
                    start_at[st][j][i] = time[j];
                    // eprintln!(
                    //     "{:?}->{:?} {} {}",
                    //     j,
                    //     i,
                    //     time_to_str(st * 6 + 60),
                    //     if time[j] == INF { "-".to_string() } else { time_to_str(time[j]) }
                    // );
                }
            }
        }
        let mut v_sq = 0;
        let mut v_ci = 0;
        for i in 0..N {
            for j in 0..N {
                if !self.input.far[i][j] {
                    continue;
                }
                for k in 0..=20 {
                    let v0 = self.input.start_at[k][i][j];
                    let v1 = start_at[k][i][j];
                    if v1 != INF && (v0 == INF || v0 < v1) {
                        // eprintln!(
                        //     "ci: {:?} {:?} {:?} {:?} {:?} {:?}",
                        //     i,
                        //     j,
                        //     k,
                        //     v0,
                        //     v1,
                        //     self.input.ws[i] * self.input.ws[j] / 10_000_000_000
                        // );
                        v_ci += self.input.ws[i] * self.input.ws[j];
                    } else {
                        v_sq += self.input.ws[i] * self.input.ws[j];
                    }
                }
            }
        }
        // eprintln!("v_sq:{:?} v_ci:{:?}", v_sq / 10_000_000_000, v_ci / 10_000_000_000);
        (v_ci as f64 / (v_ci + v_sq) as f64, start_at)
    }

    fn random_flight(&mut self) -> Vec<Flight> {
        let mut flights = vec![];
        let max_v = self.rng.next_u32() as usize % (N / 2 - N / 10 + 1) + N / 10;
        let mut now = self.rng.next_u32() as usize % 1;
        let mut pos = self.rng.next_u32() as usize % max_v;
        let mut fail = 0;
        loop {
            if now < 170 {
                let mut found = false;
                for i in 0..N / 10 {
                    let d = self.input.dist[pos][i];
                    if now + d > 180 {
                        continue;
                    }
                    let nt = if now + d < 60 { 0 } else { (now + d - 60) / 6 };
                    if self.start_at[nt][pos][i] == INF {
                        flights.push(Flight::new(pos, i, now, now + d));
                        now += d;
                        pos = i;
                        found = true;
                    }
                }
                if found {
                    continue;
                }
            }
            let mv = if fail > 10 { N - 1 } else { max_v - 1 };
            let mut next = self.rng.next_u32() as usize % mv;
            if next >= pos {
                next += 1;
            }
            let wait = self.rng.next_u32() as usize % 2;
            let d = self.input.dist[pos][next];
            if now + d + wait > 180 {
                fail += 1;
                if fail == 100 {
                    break;
                }
                continue;
            }
            flights.push(Flight::new(pos, next, now + wait, now + wait + d));
            now += wait + d;
            pos = next;
        }
        flights
    }

    fn solve(&mut self, tl: u64) -> Result {
        let mut flights = vec![];
        for _ in 0..K {
            flights.push(self.random_flight());
        }
        let (mut cur_score, start_at) = self.calc_score(&flights);
        self.start_at = start_at;
        let mut best_score = cur_score;
        let mut best_flights = flights.clone();
        let initial_cooler: f64 = env::var("IC").map_or(100.0, |v| v.parse().unwrap());
        let final_cooler: f64 = env::var("FC").map_or(1000.0, |v| v.parse().unwrap());
        let mut cooler = initial_cooler;
        let begin_time = self.timer.elapsed();
        let mut turn = 0;
        loop {
            if turn & 0xF == 0 {
                let elapsed = self.timer.elapsed();
                if elapsed > tl {
                    eprintln!("total_turn: {}", turn);
                    break;
                }
                let ratio = (elapsed - begin_time) as f64 / (TIMELIMIT - begin_time) as f64;
                cooler = (initial_cooler.ln() * (1.0 - ratio) + final_cooler.ln() * ratio).exp();
            }
            turn += 1;
            let ch_fi = self.rng.next_u32() as usize % K;
            let new_flights = self.random_flight();
            let old_flights = mem::replace(&mut flights[ch_fi], new_flights);
            let (new_score, new_start_at) = self.calc_score(&flights);
            if self.accept(new_score - cur_score, cooler) {
                cur_score = new_score;
                self.start_at = new_start_at;
                if cur_score > best_score {
                    eprintln!("best_score:{:?} at turn:{:?}", cur_score, turn);
                    best_score = cur_score;
                    best_flights = flights.clone();
                }
            } else {
                flights[ch_fi] = old_flights;
            }
        }

        Result::new(best_flights, best_score)
    }

    fn accept(&mut self, diff: f64, cooler: f64) -> bool {
        if diff >= 0.0 {
            return true;
        }
        let v = diff as f64 * cooler;
        if v < -6.0 {
            return false;
        }
        return self.rng.next_f64() < v.exp();
    }
}

fn main() {
    let input = Input::new();
    let mut solver = Solver::new(input);
    let mut best_res = Result::new_empty();
    let part = env::var("PART").map_or(1, |v| v.parse().unwrap());
    for i in 0..part {
        let result = solver.solve(solver.timer.tl() * (i + 1) / part);
        if result.score > best_res.score {
            best_res = result;
        }
    }
    best_res.output();
    eprintln!("final_score:{:?}", (best_res.score * 1e6) as i64);
}
0