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 |
|
| 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 |