提出 #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 });
}
}
提出情報
コンパイルエラー
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 |
| 結果 |
|
| セット名 |
テストケース |
| 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 |