Submission #22785943


Source Code Expand

use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::fmt;
use std::io::{stdin, stdout, BufWriter, Write};

const SIZE: usize = 30;
const V: usize = SIZE * SIZE;
const E: usize = (SIZE - 1) * SIZE + SIZE * (SIZE - 1);
const QUERIES: usize = 1000;
//const COST_LO: f64 = 1000.0;
//const COST_HI: f64 = 9000.0;

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum LogLevel {
    Critical,
    Error,
    Warning,
    Info,
    Debug,
    Debug2,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Pos {
    r: isize,
    c: isize,
}

fn diff(p0: Pos, p1: Pos) -> (isize, isize) {
    (p1.r - p0.r, p1.c - p0.c)
}

impl Pos {
    fn to_id(&self) -> usize {
        (self.r * (SIZE as isize) + self.c) as usize
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Dir {
    Right,
    Down,
    Left,
    Up,
}

impl fmt::Display for Dir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match self {
            Dir::Right => "R",
            Dir::Down => "D",
            Dir::Left => "L",
            Dir::Up => "U",
        };
        write!(f, "{}", s)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Edge {
    src: Pos,
    dest: Pos,
}

impl Edge {
    fn to_dir(&self) -> Dir {
        let (dr, dc) = diff(self.src, self.dest);
        if dr == 0 {
            if dc == 1 {
                Dir::Right
            } else if dc == -1 {
                Dir::Left
            } else {
                panic!();
            }
        } else {
            if dc != 0 {
                panic!();
            } else {
                if dr == 1 {
                    Dir::Down
                } else if dr == -1 {
                    Dir::Up
                } else {
                    panic!();
                }
            }
        }
    }

    fn to_id_impl(p: Pos, dir: Dir) -> usize {
        (match dir {
            Dir::Right => p.r * (SIZE as isize - 1) + p.c,
            Dir::Down => p.r * (SIZE as isize) + p.c + ((SIZE * (SIZE - 1)) as isize),
            _ => panic!(),
        }) as usize
    }

    fn to_id(&self) -> usize {
        match self.to_dir() {
            Dir::Left => Self::to_id_impl(self.dest, Dir::Right),
            Dir::Up => Self::to_id_impl(self.dest, Dir::Down),
            Dir::Right => Self::to_id_impl(self.src, Dir::Right),
            Dir::Down => Self::to_id_impl(self.src, Dir::Down),
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
struct Equation {
    edges: Vec<Edge>,
    cost: f64,
}

#[derive(Debug, Copy, Clone, PartialEq)]
struct EdgeWithCost {
    src: Pos,
    dest: Pos,
    cost: f64,
}

#[derive(Debug, Clone)]
struct Graph {
    edge_list: Vec<Vec<EdgeWithCost>>,
}

struct SpM {
    col_size: usize,
    row_starts: Vec<usize>,
    cols: Vec<usize>,
}

impl SpM {
    fn row_size(&self) -> usize {
        self.row_starts.len()
    }
}

fn spmv(spm: &SpM, a: &[f64], b: &mut [f64]) {
    for e in b.iter_mut() {
        *e = 0.;
    }
    for row in 0..spm.row_size() {
        let row_start = spm.row_starts[row];
        let row_end = if row < spm.row_size() - 1 {
            spm.row_starts[row + 1]
        } else {
            spm.cols.len()
        };
        for idx in row_start..row_end {
            let col = spm.cols[idx];
            b[row] += a[col];
        }
    }
}

fn spmv_trans(spm: &SpM, b: &[f64], a: &mut [f64]) {
    for e in a.iter_mut() {
        *e = 0.;
    }
    for row in 0..spm.row_size() {
        let row_start = spm.row_starts[row];
        let row_end = if row < spm.row_size() - 1 {
            spm.row_starts[row + 1]
        } else {
            spm.cols.len()
        };
        for idx in row_start..row_end {
            let col = spm.cols[idx];
            a[col] += b[row];
        }
    }
}

fn sub(x: &[f64], y: &[f64], z: &mut [f64]) {
    if x.len() != y.len() {
        panic!();
    }
    for idx in 0..x.len() {
        z[idx] = x[idx] - y[idx];
    }
}

fn scale(a: f64, x: &[f64], y: &mut [f64]) {
    for idx in 0..x.len() {
        y[idx] = a * x[idx];
    }
}

fn norm(x: &[f64]) -> f64 {
    let mut ans = 0.;
    for a in x {
        ans += a * a;
    }
    ans
}

fn clamp_vec(x: &mut [f64], min: f64, max: f64) {
    for a in x {
        *a = a.max(min).min(max);
    }
}

fn calc_default_weight(temp: f64) -> f64 {
    5000. - 1000. * temp.powf(0.15)
}

fn gradient_descent(spm: &SpM, b: &[f64], temp: f64, log_level: LogLevel) -> Vec<f64> {
    let default_weight = calc_default_weight(temp);
    let mut a = vec![default_weight; spm.col_size];
    let mut ta = vec![0.; spm.col_size];
    let mut c = vec![0.; spm.row_size()];
    let mut d = vec![0.; spm.row_size()];
    let mut sd = vec![0.; spm.row_size()];
    let alpha = 0.0001;
    for _i in 0..30 {
        spmv(spm, &a, &mut c);
        sub(&b, &c, &mut d);
        if log_level >= LogLevel::Debug {
            eprintln!("GD Diff: {}", norm(&d));
        }
        scale(alpha, &d, &mut sd);
        spmv_trans(spm, &sd, &mut ta);
        for idx in 0..spm.col_size {
            a[idx] += ta[idx];
        }
    }
    a
}

fn estimate_cost(eqs: &[Equation], temp: f64, log_level: LogLevel) -> Graph {
    let mut cols = Vec::new();
    let mut row_starts = Vec::new();
    let mut b = Vec::new();
    for eq in eqs {
        b.push(eq.cost);
        row_starts.push(cols.len());
        for e in &eq.edges {
            cols.push(e.to_id());
        }
    }
    let spm = SpM {
        col_size: E,
        row_starts,
        cols,
    };
    let mut a = gradient_descent(&spm, &b, temp, log_level);
    clamp_vec(&mut a, 1000.0, 9000.0);
    let mut edge_list = Vec::with_capacity(V);
    for row in 0..SIZE as isize {
        for col in 0..SIZE as isize {
            let v0 = Pos { r: row, c: col };
            let mut edges = Vec::with_capacity(4);
            let d = [0, 1, 0, -1, 0];
            for k in 0..4 {
                let nr = row + d[k];
                let nc = col + d[k + 1];
                if nr < 0 || nc < 0 || nr >= SIZE as isize || nc >= SIZE as isize {
                    continue;
                }
                let v1 = Pos { r: nr, c: nc };
                edges.push(EdgeWithCost {
                    src: v0,
                    dest: v1,
                    cost: a[Edge { src: v0, dest: v1 }.to_id()],
                });
            }
            edge_list.push(edges);
        }
    }
    Graph { edge_list }
}

#[derive(Debug, Copy, Clone, PartialEq)]
struct State {
    cost: f64,
    pos: Pos,
}

impl Eq for State {}

impl Ord for State {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl PartialOrd for State {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        other.cost.partial_cmp(&self.cost)
    }
}

fn dijkstra(s: Pos, t: Pos, g: &Graph) -> Vec<EdgeWithCost> {
    let mut dist: Vec<_> = (0..V).map(|_| 1e18).collect();
    let mut parent: Vec<Option<EdgeWithCost>> = (0..V).map(|_| None).collect();
    let mut heap = BinaryHeap::new();
    dist[s.to_id()] = 0.;
    heap.push(State { cost: 0., pos: s });
    while let Some(State { cost, pos }) = heap.pop() {
        if pos == t {
            break;
        }
        let i = pos.to_id();
        if cost > dist[i] {
            continue;
        }
        for e in &g.edge_list[i] {
            let next = State {
                cost: cost + e.cost,
                pos: e.dest,
            };
            let j = next.pos.to_id();
            if next.cost < dist[j] {
                dist[j] = next.cost;
                parent[j] = Some(*e);
                heap.push(next);
            }
        }
    }
    let mut edges = Vec::new();
    let mut pos = t;
    while let Some(e) = parent[pos.to_id()] {
        edges.push(e);
        pos = e.src;
    }
    edges.reverse();
    edges
}

fn solve(s: Pos, t: Pos, eqs: &[Equation], temp: f64, log_level: LogLevel) -> Vec<Edge> {
    let g = estimate_cost(eqs, temp, log_level);
    let edges = dijkstra(s, t, &g);
    edges
        .iter()
        .map(|e| Edge {
            src: e.src,
            dest: e.dest,
        })
        .collect()
}

fn respond(edges: &[Edge]) -> f64 {
    let out = stdout();
    {
        let mut out = BufWriter::new(out.lock());
        for e in edges {
            write!(out, "{}", e.to_dir()).unwrap();
        }
        writeln!(out, "").unwrap();
    }
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.split_whitespace().next().unwrap().parse().unwrap()
}

fn get_query() -> (Pos, Pos) {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    let mut nums = buf.split_whitespace();
    let rs: isize = nums.next().unwrap().parse().unwrap();
    let cs: isize = nums.next().unwrap().parse().unwrap();
    let rt: isize = nums.next().unwrap().parse().unwrap();
    let ct: isize = nums.next().unwrap().parse().unwrap();
    let s = Pos { r: rs, c: cs };
    let t = Pos { r: rt, c: ct };
    (s, t)
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let log_level = match args.iter().nth(1) {
        Some(s) => {
            if s == "-v" {
                LogLevel::Info
            } else if s == "-d" {
                LogLevel::Debug
            } else if s == "-D" {
                LogLevel::Debug2
            } else if s == "-w" {
                LogLevel::Warning
            } else if s == "-q" {
                LogLevel::Critical
            } else {
                panic!()
            }
        }
        None => LogLevel::Error,
    };
    let mut eqs = Vec::new();
    for i in 0..QUERIES {
        let temp = 0.998f64.powi(i as i32 - 1000);
        if log_level >= LogLevel::Info {
            eprintln!("Query {}, temp: {}", i, temp);
        }
        let (s, t) = get_query();
        let path = solve(s, t, &eqs, temp, log_level);
        let cost = respond(&path);
        eqs.push(Equation { edges: path, cost });
    }
}

Submission Info

Submission Time
Task A - Shortest Path Queries
User primenumber
Language Rust (1.42.0)
Score 87743696519
Code Size 10369 Byte
Status AC
Exec Time 1342 ms
Memory 4528 KiB

Judge Result

Set Name test_ALL
Score / Max Score 87743696519 / 100000000000
Status
AC × 100
Set Name Test Cases
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt
Case Name Status Exec Time Memory
test_0000.txt AC 1256 ms 4308 KiB
test_0001.txt AC 1265 ms 4284 KiB
test_0002.txt AC 1313 ms 4456 KiB
test_0003.txt AC 1287 ms 4364 KiB
test_0004.txt AC 1279 ms 4324 KiB
test_0005.txt AC 1272 ms 4228 KiB
test_0006.txt AC 1290 ms 4352 KiB
test_0007.txt AC 1342 ms 4252 KiB
test_0008.txt AC 1270 ms 4236 KiB
test_0009.txt AC 1271 ms 4476 KiB
test_0010.txt AC 1298 ms 4208 KiB
test_0011.txt AC 1287 ms 4460 KiB
test_0012.txt AC 1262 ms 4432 KiB
test_0013.txt AC 1276 ms 4444 KiB
test_0014.txt AC 1277 ms 4324 KiB
test_0015.txt AC 1280 ms 4192 KiB
test_0016.txt AC 1247 ms 4340 KiB
test_0017.txt AC 1254 ms 4340 KiB
test_0018.txt AC 1260 ms 4452 KiB
test_0019.txt AC 1314 ms 4272 KiB
test_0020.txt AC 1285 ms 4300 KiB
test_0021.txt AC 1267 ms 4440 KiB
test_0022.txt AC 1291 ms 4260 KiB
test_0023.txt AC 1267 ms 4416 KiB
test_0024.txt AC 1273 ms 4320 KiB
test_0025.txt AC 1275 ms 4204 KiB
test_0026.txt AC 1258 ms 4144 KiB
test_0027.txt AC 1248 ms 4256 KiB
test_0028.txt AC 1291 ms 4380 KiB
test_0029.txt AC 1299 ms 4288 KiB
test_0030.txt AC 1292 ms 4468 KiB
test_0031.txt AC 1296 ms 4364 KiB
test_0032.txt AC 1297 ms 4344 KiB
test_0033.txt AC 1265 ms 4336 KiB
test_0034.txt AC 1280 ms 4316 KiB
test_0035.txt AC 1241 ms 4264 KiB
test_0036.txt AC 1271 ms 4420 KiB
test_0037.txt AC 1267 ms 4336 KiB
test_0038.txt AC 1292 ms 4344 KiB
test_0039.txt AC 1255 ms 4264 KiB
test_0040.txt AC 1283 ms 4392 KiB
test_0041.txt AC 1285 ms 4368 KiB
test_0042.txt AC 1270 ms 4308 KiB
test_0043.txt AC 1266 ms 4356 KiB
test_0044.txt AC 1311 ms 4260 KiB
test_0045.txt AC 1278 ms 4260 KiB
test_0046.txt AC 1270 ms 4192 KiB
test_0047.txt AC 1269 ms 4436 KiB
test_0048.txt AC 1291 ms 4324 KiB
test_0049.txt AC 1293 ms 4228 KiB
test_0050.txt AC 1268 ms 4252 KiB
test_0051.txt AC 1279 ms 4196 KiB
test_0052.txt AC 1273 ms 4456 KiB
test_0053.txt AC 1274 ms 4452 KiB
test_0054.txt AC 1286 ms 4316 KiB
test_0055.txt AC 1281 ms 4324 KiB
test_0056.txt AC 1299 ms 4160 KiB
test_0057.txt AC 1285 ms 4384 KiB
test_0058.txt AC 1275 ms 4272 KiB
test_0059.txt AC 1269 ms 4332 KiB
test_0060.txt AC 1289 ms 4356 KiB
test_0061.txt AC 1278 ms 4416 KiB
test_0062.txt AC 1278 ms 4304 KiB
test_0063.txt AC 1329 ms 4380 KiB
test_0064.txt AC 1289 ms 4304 KiB
test_0065.txt AC 1301 ms 4228 KiB
test_0066.txt AC 1287 ms 4208 KiB
test_0067.txt AC 1277 ms 4360 KiB
test_0068.txt AC 1284 ms 4292 KiB
test_0069.txt AC 1260 ms 4348 KiB
test_0070.txt AC 1259 ms 4428 KiB
test_0071.txt AC 1255 ms 4328 KiB
test_0072.txt AC 1255 ms 4328 KiB
test_0073.txt AC 1275 ms 4368 KiB
test_0074.txt AC 1275 ms 4356 KiB
test_0075.txt AC 1275 ms 4328 KiB
test_0076.txt AC 1285 ms 4184 KiB
test_0077.txt AC 1269 ms 4432 KiB
test_0078.txt AC 1255 ms 4256 KiB
test_0079.txt AC 1285 ms 4296 KiB
test_0080.txt AC 1271 ms 4312 KiB
test_0081.txt AC 1255 ms 4272 KiB
test_0082.txt AC 1269 ms 4156 KiB
test_0083.txt AC 1292 ms 4292 KiB
test_0084.txt AC 1277 ms 4352 KiB
test_0085.txt AC 1278 ms 4424 KiB
test_0086.txt AC 1254 ms 4340 KiB
test_0087.txt AC 1256 ms 4468 KiB
test_0088.txt AC 1279 ms 4184 KiB
test_0089.txt AC 1294 ms 4408 KiB
test_0090.txt AC 1278 ms 4368 KiB
test_0091.txt AC 1277 ms 4244 KiB
test_0092.txt AC 1278 ms 4220 KiB
test_0093.txt AC 1268 ms 4236 KiB
test_0094.txt AC 1285 ms 4320 KiB
test_0095.txt AC 1254 ms 4084 KiB
test_0096.txt AC 1295 ms 4380 KiB
test_0097.txt AC 1287 ms 4320 KiB
test_0098.txt AC 1265 ms 4272 KiB
test_0099.txt AC 1283 ms 4528 KiB