結果
問題 | No.5006 Hidden Maze |
ユーザー | terry_u16 |
提出日時 | 2022-06-12 17:26:41 |
言語 | Rust (1.77.0 + proconio) |
結果 |
AC
|
実行時間 | 505 ms / 2,000 ms |
コード長 | 14,922 bytes |
コンパイル時間 | 1,390 ms |
実行使用メモリ | 22,856 KB |
スコア | 71,991 |
平均クエリ数 | 281.09 |
最終ジャッジ日時 | 2022-06-12 17:27:34 |
合計ジャッジ時間 | 50,879 ms |
ジャッジサーバーID (参考情報) |
judge13 / judge12 |
純コード判定しない問題か言語 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 427 ms
22,228 KB |
testcase_01 | AC | 474 ms
22,004 KB |
testcase_02 | AC | 423 ms
21,756 KB |
testcase_03 | AC | 425 ms
22,716 KB |
testcase_04 | AC | 446 ms
22,004 KB |
testcase_05 | AC | 428 ms
21,756 KB |
testcase_06 | AC | 458 ms
21,992 KB |
testcase_07 | AC | 448 ms
21,780 KB |
testcase_08 | AC | 476 ms
21,768 KB |
testcase_09 | AC | 462 ms
22,216 KB |
testcase_10 | AC | 412 ms
21,992 KB |
testcase_11 | AC | 439 ms
21,940 KB |
testcase_12 | AC | 431 ms
21,904 KB |
testcase_13 | AC | 441 ms
21,892 KB |
testcase_14 | AC | 452 ms
21,892 KB |
testcase_15 | AC | 413 ms
22,600 KB |
testcase_16 | AC | 427 ms
22,216 KB |
testcase_17 | AC | 426 ms
21,792 KB |
testcase_18 | AC | 468 ms
21,940 KB |
testcase_19 | AC | 479 ms
21,952 KB |
testcase_20 | AC | 414 ms
21,892 KB |
testcase_21 | AC | 433 ms
21,928 KB |
testcase_22 | AC | 420 ms
21,904 KB |
testcase_23 | AC | 415 ms
22,572 KB |
testcase_24 | AC | 443 ms
22,456 KB |
testcase_25 | AC | 442 ms
21,780 KB |
testcase_26 | AC | 495 ms
22,216 KB |
testcase_27 | AC | 492 ms
21,952 KB |
testcase_28 | AC | 499 ms
21,780 KB |
testcase_29 | AC | 485 ms
21,904 KB |
testcase_30 | AC | 426 ms
21,940 KB |
testcase_31 | AC | 425 ms
21,892 KB |
testcase_32 | AC | 440 ms
22,004 KB |
testcase_33 | AC | 426 ms
22,444 KB |
testcase_34 | AC | 443 ms
22,004 KB |
testcase_35 | AC | 416 ms
21,928 KB |
testcase_36 | AC | 420 ms
21,892 KB |
testcase_37 | AC | 505 ms
22,588 KB |
testcase_38 | AC | 459 ms
22,228 KB |
testcase_39 | AC | 412 ms
21,952 KB |
testcase_40 | AC | 423 ms
22,844 KB |
testcase_41 | AC | 445 ms
21,756 KB |
testcase_42 | AC | 420 ms
22,288 KB |
testcase_43 | AC | 433 ms
21,928 KB |
testcase_44 | AC | 434 ms
21,780 KB |
testcase_45 | AC | 437 ms
21,952 KB |
testcase_46 | AC | 492 ms
22,856 KB |
testcase_47 | AC | 452 ms
21,952 KB |
testcase_48 | AC | 494 ms
22,444 KB |
testcase_49 | AC | 476 ms
21,780 KB |
testcase_50 | AC | 440 ms
21,928 KB |
testcase_51 | AC | 424 ms
22,252 KB |
testcase_52 | AC | 419 ms
21,940 KB |
testcase_53 | AC | 433 ms
21,992 KB |
testcase_54 | AC | 478 ms
21,892 KB |
testcase_55 | AC | 420 ms
21,928 KB |
testcase_56 | AC | 428 ms
22,600 KB |
testcase_57 | AC | 475 ms
21,940 KB |
testcase_58 | AC | 501 ms
22,276 KB |
testcase_59 | AC | 440 ms
22,624 KB |
testcase_60 | AC | 444 ms
22,144 KB |
testcase_61 | AC | 434 ms
22,228 KB |
testcase_62 | AC | 415 ms
22,564 KB |
testcase_63 | AC | 438 ms
22,216 KB |
testcase_64 | AC | 469 ms
21,904 KB |
testcase_65 | AC | 422 ms
22,216 KB |
testcase_66 | AC | 420 ms
21,780 KB |
testcase_67 | AC | 465 ms
21,904 KB |
testcase_68 | AC | 468 ms
21,892 KB |
testcase_69 | AC | 446 ms
22,288 KB |
testcase_70 | AC | 444 ms
21,904 KB |
testcase_71 | AC | 438 ms
22,240 KB |
testcase_72 | AC | 434 ms
21,952 KB |
testcase_73 | AC | 468 ms
22,228 KB |
testcase_74 | AC | 476 ms
21,784 KB |
testcase_75 | AC | 442 ms
22,600 KB |
testcase_76 | AC | 424 ms
21,964 KB |
testcase_77 | AC | 490 ms
22,456 KB |
testcase_78 | AC | 419 ms
22,228 KB |
testcase_79 | AC | 423 ms
21,880 KB |
testcase_80 | AC | 430 ms
22,264 KB |
testcase_81 | AC | 412 ms
21,964 KB |
testcase_82 | AC | 412 ms
22,288 KB |
testcase_83 | AC | 416 ms
22,228 KB |
testcase_84 | AC | 441 ms
22,564 KB |
testcase_85 | AC | 411 ms
21,928 KB |
testcase_86 | AC | 432 ms
22,612 KB |
testcase_87 | AC | 456 ms
22,456 KB |
testcase_88 | AC | 413 ms
22,444 KB |
testcase_89 | AC | 444 ms
22,216 KB |
testcase_90 | AC | 440 ms
21,992 KB |
testcase_91 | AC | 432 ms
21,780 KB |
testcase_92 | AC | 422 ms
21,880 KB |
testcase_93 | AC | 406 ms
22,216 KB |
testcase_94 | AC | 444 ms
21,940 KB |
testcase_95 | AC | 428 ms
21,904 KB |
testcase_96 | AC | 417 ms
21,940 KB |
testcase_97 | AC | 493 ms
21,892 KB |
testcase_98 | AC | 466 ms
21,768 KB |
testcase_99 | AC | 452 ms
22,632 KB |
ソースコード
use std::collections::BinaryHeap; use grid::{Coordinate, Map2d, ADJACENTS, DIRECTIONS}; #[allow(unused_macros)] macro_rules! chmin { ($base:expr, $($cmps:expr),+ $(,)*) => {{ let cmp_min = min!($($cmps),+); if $base > cmp_min { $base = cmp_min; true } else { false } }}; } #[allow(unused_macros)] macro_rules! chmax { ($base:expr, $($cmps:expr),+ $(,)*) => {{ let cmp_max = max!($($cmps),+); if $base < cmp_max { $base = cmp_max; true } else { false } }}; } #[allow(unused_macros)] macro_rules! min { ($a:expr $(,)*) => {{ $a }}; ($a:expr, $b:expr $(,)*) => {{ std::cmp::min($a, $b) }}; ($a:expr, $($rest:expr),+ $(,)*) => {{ std::cmp::min($a, min!($($rest),+)) }}; } #[allow(unused_macros)] macro_rules! max { ($a:expr $(,)*) => {{ $a }}; ($a:expr, $b:expr $(,)*) => {{ std::cmp::max($a, $b) }}; ($a:expr, $($rest:expr),+ $(,)*) => {{ std::cmp::max($a, max!($($rest),+)) }}; } macro_rules! get { ($t:ty) => { { let mut line: String = String::new(); std::io::stdin().read_line(&mut line).unwrap(); line.trim().parse::<$t>().unwrap() } }; ($($t:ty),*) => { { let mut line: String = String::new(); std::io::stdin().read_line(&mut line).unwrap(); let mut iter = line.split_whitespace(); ( $(iter.next().unwrap().parse::<$t>().unwrap(),)* ) } }; ($t:ty; $n:expr) => { (0..$n).map(|_| get!($t) ).collect::<Vec<_>>() }; ($($t:ty),*; $n:expr) => { (0..$n).map(|_| get!($($t),*) ).collect::<Vec<_>>() }; ($t:ty ;;) => { { let mut line: String = String::new(); std::io::stdin().read_line(&mut line).unwrap(); line.split_whitespace() .map(|t| t.parse::<$t>().unwrap()) .collect::<Vec<_>>() } }; ($t:ty ;; $n:expr) => { (0..$n).map(|_| get!($t ;;)).collect::<Vec<_>>() }; } const MAP_SIZE: usize = 20; #[derive(Debug, Clone, Copy)] struct Input { p: f64, } #[derive(Debug, Clone)] struct State { map: Map2d<[Edge; 4]>, } #[derive(Debug, Clone, Copy)] struct Edge { next: Option<Coordinate>, state: EdgeState, } impl Edge { fn new(next: Option<Coordinate>, state: EdgeState) -> Self { Self { next, state } } } #[derive(Debug, Clone, Copy)] enum EdgeState { NotEnter, NoWall, MayBeWall(i32), } impl EdgeState { #[inline] fn prob(&self, p: f64, default: f64) -> f64 { let success = 1.0 - p; match self { EdgeState::NotEnter => default * success, EdgeState::NoWall => success, EdgeState::MayBeWall(c) => p.powi(*c) * success, } } } // Partial orderなものをTotal orderにする #[derive(PartialEq, PartialOrd)] pub struct Total<T>(pub T); impl<T: PartialEq> Eq for Total<T> {} impl<T: PartialOrd> Ord for Total<T> { fn cmp(&self, other: &Total<T>) -> std::cmp::Ordering { self.0.partial_cmp(&other.0).unwrap() } } fn main() { let (input, state) = read_input(); let score = solve(&input, state); eprintln!("score: {}", score); } fn read_input() -> (Input, State) { let (_, _, p) = get!(usize, usize, i64); let p = p as f64 * 0.01; let mut map = Map2d::new( vec![[Edge::new(None, EdgeState::NotEnter); 4]; MAP_SIZE * MAP_SIZE], MAP_SIZE, ); for row in 0..MAP_SIZE { for col in 0..MAP_SIZE { let c = Coordinate::new(row, col); for (dir, adj) in ADJACENTS.iter().enumerate() { let next = c + *adj; if next.in_map(MAP_SIZE) { map[c][dir].next = Some(next); } } } } let input = Input { p }; let state = State { map }; (input, state) } fn solve(input: &Input, mut state: State) -> i64 { let prob_map = gen_prob(); for trial in 0.. { let moves = dijkstra(input, &state, &prob_map); if let Some(stop) = write_output(&moves) { update_state(&mut state, &moves[..stop], moves[stop]) } else { return 1001 - trial - 1; } } 0 } fn dijkstra(input: &Input, state: &State, prob_map: &Map2d<[f64; 4]>) -> Vec<usize> { let mut distances = Map2d::new(vec![0.0; MAP_SIZE * MAP_SIZE], MAP_SIZE); let mut from = Map2d::new(vec![0; MAP_SIZE * MAP_SIZE], MAP_SIZE); let mut queue = BinaryHeap::new(); distances[Coordinate::new(0, 0)] = 1.0; queue.push((Total(1.0), Coordinate::new(0, 0))); let goal = Coordinate::new(MAP_SIZE - 1, MAP_SIZE - 1); while let Some((Total(p), c)) = queue.pop() { if distances[c] < p { continue; } if c == goal { break; } for dir in 0..4 { let edge = state.map[c][dir]; if let Some(next) = edge.next { let diff = (c.row as f64 - c.col as f64).abs(); let prob = edge .state .prob(input.p, prob_map[c][dir] - 1e-3 * diff) .max(0.0); let next_p = p * prob; if chmax!(distances[next], next_p) { from[next] = dir; queue.push((Total(next_p), next)); } } } } let mut current = goal; let mut moves = vec![]; while current != Coordinate::new(0, 0) { let dir = from[current]; moves.push(dir); current = current + ADJACENTS[dir ^ 2]; } moves.reverse(); moves } fn update_state(state: &mut State, ok: &[usize], ng: usize) { let mut current = Coordinate::new(0, 0); for &ok in ok { state.map[current][ok].state = EdgeState::NoWall; current = current + ADJACENTS[ok]; state.map[current][ok ^ 2].state = EdgeState::NoWall; } state.map[current][ng].state = match state.map[current][ng].state { EdgeState::NotEnter => EdgeState::MayBeWall(1), EdgeState::NoWall => EdgeState::NoWall, EdgeState::MayBeWall(c) => EdgeState::MayBeWall(c + 1), }; current = current + ADJACENTS[ng]; state.map[current][ng ^ 2].state = match state.map[current][ng ^ 2].state { EdgeState::NotEnter => EdgeState::MayBeWall(1), EdgeState::NoWall => EdgeState::NoWall, EdgeState::MayBeWall(c) => EdgeState::MayBeWall(c + 1), }; } fn write_output(moves: &[usize]) -> Option<usize> { let output = moves.iter().map(|dir| DIRECTIONS[*dir]).collect::<String>(); println!("{}", output); let judge = get!(i64); if judge == -1 { None } else { Some(judge as usize) } } fn gen_prob() -> Map2d<[f64; 4]> { const TRIAL_COUNT: usize = 200; let mut map = Map2d::new(vec![[0.0; 4]; MAP_SIZE * MAP_SIZE], MAP_SIZE); for seed in 0..TRIAL_COUNT { let rand_map = gen_map(seed as u64 + 42); for row in 0..MAP_SIZE { for col in 0..MAP_SIZE { let c = Coordinate::new(row, col); for dir in 0..4 { if rand_map[c][dir].is_some() { map[c][dir] += 1.0 / TRIAL_COUNT as f64; } } } } } map } fn gen_map(seed: u64) -> Map2d<[Option<Coordinate>; 4]> { let mut rng = Xorshift::with_seed(seed); let wall_count = rng.rand(101) + 100; let mut map = Map2d::new(vec![[None; 4]; MAP_SIZE * MAP_SIZE], MAP_SIZE); for row in 0..MAP_SIZE { for col in 0..MAP_SIZE { let c = Coordinate::new(row, col); for adj in 0..4 { let next = c + ADJACENTS[adj]; if next.in_map(MAP_SIZE) { map[c][adj] = Some(next); } } } } const U: usize = 0; const R: usize = 1; const D: usize = 2; const L: usize = 3; for _ in 0..wall_count { loop { let d = rng.rand(2); if d == 0 { let row = rng.rand(MAP_SIZE as u64) as usize; let col = rng.rand(MAP_SIZE as u64 - 1) as usize; let c = Coordinate::new(row, col); let next = c + ADJACENTS[R]; if map[c][R].is_some() { map[c][R] = None; map[next][L] = None; let mut seen = Map2d::new(vec![false; MAP_SIZE * MAP_SIZE], MAP_SIZE); if dfs(c, &mut seen, &map) == MAP_SIZE * MAP_SIZE { break; } map[c][R] = Some(next); map[next][L] = Some(c); } } else { let row = rng.rand(MAP_SIZE as u64 - 1) as usize; let col = rng.rand(MAP_SIZE as u64) as usize; let c = Coordinate::new(row, col); let next = c + ADJACENTS[D]; if map[c][D].is_some() { map[c][D] = None; map[next][U] = None; let mut seen = Map2d::new(vec![false; MAP_SIZE * MAP_SIZE], MAP_SIZE); if dfs(c, &mut seen, &map) == MAP_SIZE * MAP_SIZE { break; } map[c][D] = Some(next); map[next][U] = Some(c); } } } } map } fn dfs(current: Coordinate, seen: &mut Map2d<bool>, map: &Map2d<[Option<Coordinate>; 4]>) -> usize { let mut count = 1; seen[current] = true; for dir in 0..4 { if let Some(next) = map[current][dir] { if seen[next] { continue; } count += dfs(next, seen, map); } } count } #[derive(Debug)] #[allow(dead_code)] pub struct Xorshift { seed: u64, } impl Xorshift { #[allow(dead_code)] pub fn new() -> Xorshift { Xorshift { seed: 0xf0fb588ca2196dac, } } #[allow(dead_code)] pub fn with_seed(seed: u64) -> Xorshift { Xorshift { seed: seed } } #[inline] #[allow(dead_code)] pub fn next(&mut self) -> u64 { self.seed = self.seed ^ (self.seed << 13); self.seed = self.seed ^ (self.seed >> 7); self.seed = self.seed ^ (self.seed << 17); self.seed } #[inline] #[allow(dead_code)] pub fn rand(&mut self, m: u64) -> u64 { self.next() % m } #[inline] #[allow(dead_code)] // 0.0 ~ 1.0 pub fn randf(&mut self) -> f64 { use std::mem; const UPPER_MASK: u64 = 0x3FF0000000000000; const LOWER_MASK: u64 = 0xFFFFFFFFFFFFF; let tmp = UPPER_MASK | (self.next() & LOWER_MASK); let result: f64 = unsafe { mem::transmute(tmp) }; result - 1.0 } } #[allow(dead_code)] mod grid { #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct Coordinate { pub row: usize, pub col: usize, } impl Coordinate { pub const fn new(row: usize, col: usize) -> Self { Self { row, col } } pub fn in_map(&self, size: usize) -> bool { self.row < size && self.col < size } pub const fn to_index(&self, size: usize) -> usize { self.row * size + self.col } pub const fn dist(&self, other: &Self) -> usize { Self::dist_1d(self.row, other.row) + Self::dist_1d(self.col, other.col) } const fn dist_1d(x0: usize, x1: usize) -> usize { (x0 as i64 - x1 as i64).abs() as usize } } #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub struct CoordinateDiff { pub dr: usize, pub dc: usize, } impl CoordinateDiff { pub const fn new(dr: usize, dc: usize) -> Self { Self { dr, dc } } pub const fn invert(&self) -> Self { Self::new(0usize.wrapping_sub(self.dr), 0usize.wrapping_sub(self.dc)) } } impl std::ops::Add<CoordinateDiff> for Coordinate { type Output = Coordinate; fn add(self, rhs: CoordinateDiff) -> Self::Output { Coordinate::new(self.row.wrapping_add(rhs.dr), self.col.wrapping_add(rhs.dc)) } } pub const ADJACENTS: [CoordinateDiff; 4] = [ CoordinateDiff::new(!0, 0), CoordinateDiff::new(0, 1), CoordinateDiff::new(1, 0), CoordinateDiff::new(0, !0), ]; pub const DIRECTIONS: [char; 4] = ['U', 'R', 'D', 'L']; #[derive(Debug, Clone)] pub struct Map2d<T> { pub width: usize, pub height: usize, map: Vec<T>, } impl<T> Map2d<T> { pub fn new(map: Vec<T>, width: usize) -> Self { let height = map.len() / width; debug_assert!(width * height == map.len()); Self { width, height, map } } } impl<T> std::ops::Index<Coordinate> for Map2d<T> { type Output = T; #[inline] fn index(&self, coordinate: Coordinate) -> &Self::Output { &self.map[coordinate.row * self.width + coordinate.col] } } impl<T> std::ops::IndexMut<Coordinate> for Map2d<T> { #[inline] fn index_mut(&mut self, coordinate: Coordinate) -> &mut Self::Output { &mut self.map[coordinate.row * self.width + coordinate.col] } } impl<T> std::ops::Index<&Coordinate> for Map2d<T> { type Output = T; #[inline] fn index(&self, coordinate: &Coordinate) -> &Self::Output { &self.map[coordinate.row * self.width + coordinate.col] } } impl<T> std::ops::IndexMut<&Coordinate> for Map2d<T> { #[inline] fn index_mut(&mut self, coordinate: &Coordinate) -> &mut Self::Output { &mut self.map[coordinate.row * self.width + coordinate.col] } } impl<T> std::ops::Index<usize> for Map2d<T> { type Output = [T]; #[inline] fn index(&self, row: usize) -> &Self::Output { let begin = row * self.width; let end = begin + self.width; &self.map[begin..end] } } impl<T> std::ops::IndexMut<usize> for Map2d<T> { #[inline] fn index_mut(&mut self, row: usize) -> &mut Self::Output { let begin = row * self.width; let end = begin + self.width; &mut self.map[begin..end] } } }