提出 #22784737


ソースコード 拡げる

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]) -> Vec<f64> {
    let mut b = vec![0.; spm.row_size()];
    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];
        }
    }
    b
}

fn spmv_trans(spm: &SpM, b: &[f64]) -> Vec<f64> {
    let mut a = vec![0.; spm.col_size];
    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];
        }
    }
    a
}

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

fn scale(a: f64, x: &[f64]) -> Vec<f64> {
    let mut z = vec![0.; x.len()];
    for idx in 0..x.len() {
        z[idx] = a * x[idx];
    }
    z
}

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

fn estimate_cost(eqs: &[Equation], 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, log_level);
    clamp_vec(&mut a, 1000.0, 9000.0);
    let mut edge_list = Vec::new();
    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::new();
            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], log_level: LogLevel) -> Vec<Edge> {
    let g = estimate_cost(eqs, 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 {
                panic!()
            }
        }
        None => LogLevel::Error,
    };
    let mut eqs = Vec::new();
    for _i in 0..QUERIES {
        let (s, t) = get_query();
        let path = solve(s, t, &eqs, log_level);
        let cost = respond(&path);
        eqs.push(Equation { edges: path, cost });
    }
}

提出情報

提出日時
問題 A - Shortest Path Queries
ユーザ primenumber
言語 Rust (1.42.0)
得点 81586691747
コード長 9671 Byte
結果 AC
実行時間 1203 ms
メモリ 3816 KiB

コンパイルエラー

warning: variant is never constructed: `Critical`
  --> src/main.rs:15:5
   |
15 |     Critical,
   |     ^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: variant is never constructed: `Warning`
  --> src/main.rs:17:5
   |
17 |     Warning,
   |     ^^^^^^^

warning: variant is never constructed: `Debug2`
  --> src/main.rs:20:5
   |
20 |     Debug2,
   |     ^^^^^^

ジャッジ結果

セット名 test_ALL
得点 / 配点 81586691747 / 100000000000
結果
AC × 100
セット名 テストケース
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
ケース名 結果 実行時間 メモリ
test_0000.txt AC 1047 ms 3748 KiB
test_0001.txt AC 1043 ms 3764 KiB
test_0002.txt AC 1098 ms 3812 KiB
test_0003.txt AC 1058 ms 3808 KiB
test_0004.txt AC 1085 ms 3664 KiB
test_0005.txt AC 1058 ms 3736 KiB
test_0006.txt AC 1061 ms 3624 KiB
test_0007.txt AC 1203 ms 3620 KiB
test_0008.txt AC 1107 ms 3644 KiB
test_0009.txt AC 1051 ms 3716 KiB
test_0010.txt AC 1065 ms 3624 KiB
test_0011.txt AC 1153 ms 3720 KiB
test_0012.txt AC 1040 ms 3736 KiB
test_0013.txt AC 1064 ms 3776 KiB
test_0014.txt AC 1131 ms 3720 KiB
test_0015.txt AC 1069 ms 3728 KiB
test_0016.txt AC 1032 ms 3624 KiB
test_0017.txt AC 1121 ms 3736 KiB
test_0018.txt AC 1063 ms 3676 KiB
test_0019.txt AC 1163 ms 3720 KiB
test_0020.txt AC 1067 ms 3732 KiB
test_0021.txt AC 1039 ms 3772 KiB
test_0022.txt AC 1147 ms 3684 KiB
test_0023.txt AC 1046 ms 3716 KiB
test_0024.txt AC 1042 ms 3740 KiB
test_0025.txt AC 1080 ms 3812 KiB
test_0026.txt AC 1040 ms 3628 KiB
test_0027.txt AC 1043 ms 3720 KiB
test_0028.txt AC 1066 ms 3812 KiB
test_0029.txt AC 1084 ms 3736 KiB
test_0030.txt AC 1075 ms 3748 KiB
test_0031.txt AC 1093 ms 3724 KiB
test_0032.txt AC 1105 ms 3812 KiB
test_0033.txt AC 1093 ms 3640 KiB
test_0034.txt AC 1143 ms 3736 KiB
test_0035.txt AC 1031 ms 3712 KiB
test_0036.txt AC 1061 ms 3808 KiB
test_0037.txt AC 1035 ms 3744 KiB
test_0038.txt AC 1058 ms 3628 KiB
test_0039.txt AC 1056 ms 3624 KiB
test_0040.txt AC 1058 ms 3628 KiB
test_0041.txt AC 1069 ms 3624 KiB
test_0042.txt AC 1076 ms 3732 KiB
test_0043.txt AC 1098 ms 3728 KiB
test_0044.txt AC 1140 ms 3740 KiB
test_0045.txt AC 1064 ms 3668 KiB
test_0046.txt AC 1070 ms 3764 KiB
test_0047.txt AC 1042 ms 3740 KiB
test_0048.txt AC 1081 ms 3624 KiB
test_0049.txt AC 1062 ms 3748 KiB
test_0050.txt AC 1046 ms 3728 KiB
test_0051.txt AC 1052 ms 3732 KiB
test_0052.txt AC 1057 ms 3716 KiB
test_0053.txt AC 1054 ms 3628 KiB
test_0054.txt AC 1062 ms 3624 KiB
test_0055.txt AC 1130 ms 3628 KiB
test_0056.txt AC 1075 ms 3732 KiB
test_0057.txt AC 1061 ms 3740 KiB
test_0058.txt AC 1073 ms 3700 KiB
test_0059.txt AC 1058 ms 3660 KiB
test_0060.txt AC 1143 ms 3744 KiB
test_0061.txt AC 1080 ms 3620 KiB
test_0062.txt AC 1053 ms 3744 KiB
test_0063.txt AC 1200 ms 3816 KiB
test_0064.txt AC 1083 ms 3712 KiB
test_0065.txt AC 1079 ms 3732 KiB
test_0066.txt AC 1070 ms 3728 KiB
test_0067.txt AC 1077 ms 3716 KiB
test_0068.txt AC 1064 ms 3624 KiB
test_0069.txt AC 1058 ms 3624 KiB
test_0070.txt AC 1046 ms 3620 KiB
test_0071.txt AC 1030 ms 3772 KiB
test_0072.txt AC 1106 ms 3716 KiB
test_0073.txt AC 1091 ms 3636 KiB
test_0074.txt AC 1048 ms 3772 KiB
test_0075.txt AC 1049 ms 3624 KiB
test_0076.txt AC 1061 ms 3776 KiB
test_0077.txt AC 1053 ms 3736 KiB
test_0078.txt AC 1059 ms 3780 KiB
test_0079.txt AC 1050 ms 3680 KiB
test_0080.txt AC 1053 ms 3736 KiB
test_0081.txt AC 1074 ms 3776 KiB
test_0082.txt AC 1125 ms 3624 KiB
test_0083.txt AC 1042 ms 3812 KiB
test_0084.txt AC 1072 ms 3704 KiB
test_0085.txt AC 1056 ms 3712 KiB
test_0086.txt AC 1061 ms 3676 KiB
test_0087.txt AC 1051 ms 3736 KiB
test_0088.txt AC 1062 ms 3732 KiB
test_0089.txt AC 1065 ms 3680 KiB
test_0090.txt AC 1070 ms 3628 KiB
test_0091.txt AC 1051 ms 3708 KiB
test_0092.txt AC 1038 ms 3776 KiB
test_0093.txt AC 1044 ms 3716 KiB
test_0094.txt AC 1077 ms 3676 KiB
test_0095.txt AC 1033 ms 3680 KiB
test_0096.txt AC 1062 ms 3728 KiB
test_0097.txt AC 1094 ms 3712 KiB
test_0098.txt AC 1048 ms 3816 KiB
test_0099.txt AC 1152 ms 3740 KiB