結果

問題 No.5006 Hidden Maze
ユーザー terry_u16terry_u16
提出日時 2022-06-12 16:22:37
言語 Rust
(1.77.0 + proconio)
結果
AC  
実行時間 1,087 ms / 2,000 ms
コード長 10,160 bytes
コンパイル時間 1,501 ms
実行使用メモリ 22,796 KB
スコア 62,405
平均クエリ数 376.95
最終ジャッジ日時 2022-06-12 16:23:28
合計ジャッジ時間 46,053 ms
ジャッジサーバーID
(参考情報)
judge15 / judge13
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 163 ms
21,780 KB
testcase_01 AC 270 ms
21,880 KB
testcase_02 AC 32 ms
21,928 KB
testcase_03 AC 221 ms
22,588 KB
testcase_04 AC 249 ms
21,940 KB
testcase_05 AC 295 ms
21,952 KB
testcase_06 AC 666 ms
22,204 KB
testcase_07 AC 643 ms
21,768 KB
testcase_08 AC 1,007 ms
22,396 KB
testcase_09 AC 992 ms
21,768 KB
testcase_10 AC 83 ms
22,228 KB
testcase_11 AC 94 ms
21,892 KB
testcase_12 AC 167 ms
22,600 KB
testcase_13 AC 187 ms
22,444 KB
testcase_14 AC 367 ms
21,880 KB
testcase_15 AC 106 ms
21,928 KB
testcase_16 AC 451 ms
22,276 KB
testcase_17 AC 234 ms
22,276 KB
testcase_18 AC 244 ms
22,240 KB
testcase_19 AC 95 ms
22,004 KB
testcase_20 AC 131 ms
21,712 KB
testcase_21 AC 125 ms
22,624 KB
testcase_22 AC 174 ms
22,576 KB
testcase_23 AC 199 ms
22,588 KB
testcase_24 AC 487 ms
22,612 KB
testcase_25 AC 615 ms
22,576 KB
testcase_26 AC 1,087 ms
22,396 KB
testcase_27 AC 725 ms
21,904 KB
testcase_28 AC 395 ms
22,612 KB
testcase_29 AC 1,021 ms
21,896 KB
testcase_30 AC 90 ms
21,916 KB
testcase_31 AC 78 ms
22,276 KB
testcase_32 AC 232 ms
22,456 KB
testcase_33 AC 179 ms
22,276 KB
testcase_34 AC 194 ms
22,456 KB
testcase_35 AC 193 ms
22,276 KB
testcase_36 AC 902 ms
21,940 KB
testcase_37 AC 1,004 ms
21,892 KB
testcase_38 AC 1,006 ms
22,796 KB
testcase_39 AC 1,004 ms
21,952 KB
testcase_40 AC 139 ms
22,276 KB
testcase_41 AC 102 ms
21,952 KB
testcase_42 AC 138 ms
21,952 KB
testcase_43 AC 224 ms
21,780 KB
testcase_44 AC 65 ms
22,600 KB
testcase_45 AC 265 ms
22,716 KB
testcase_46 AC 1,008 ms
21,952 KB
testcase_47 AC 506 ms
21,780 KB
testcase_48 AC 879 ms
22,444 KB
testcase_49 AC 631 ms
21,904 KB
testcase_50 AC 89 ms
22,276 KB
testcase_51 AC 185 ms
21,940 KB
testcase_52 AC 169 ms
21,892 KB
testcase_53 AC 271 ms
21,768 KB
testcase_54 AC 355 ms
22,228 KB
testcase_55 AC 219 ms
22,548 KB
testcase_56 AC 205 ms
21,892 KB
testcase_57 AC 302 ms
22,228 KB
testcase_58 AC 827 ms
21,992 KB
testcase_59 AC 461 ms
22,396 KB
testcase_60 AC 86 ms
21,980 KB
testcase_61 AC 123 ms
21,952 KB
testcase_62 AC 155 ms
21,768 KB
testcase_63 AC 243 ms
21,992 KB
testcase_64 AC 381 ms
22,004 KB
testcase_65 AC 81 ms
21,892 KB
testcase_66 AC 483 ms
21,940 KB
testcase_67 AC 157 ms
21,768 KB
testcase_68 AC 652 ms
22,204 KB
testcase_69 AC 927 ms
21,940 KB
testcase_70 AC 48 ms
21,940 KB
testcase_71 AC 120 ms
21,576 KB
testcase_72 AC 65 ms
21,832 KB
testcase_73 AC 157 ms
22,564 KB
testcase_74 AC 38 ms
21,952 KB
testcase_75 AC 412 ms
22,548 KB
testcase_76 AC 34 ms
22,084 KB
testcase_77 AC 1,014 ms
21,904 KB
testcase_78 AC 249 ms
21,768 KB
testcase_79 AC 1,059 ms
21,904 KB
testcase_80 AC 45 ms
21,768 KB
testcase_81 AC 201 ms
21,780 KB
testcase_82 AC 145 ms
21,968 KB
testcase_83 AC 75 ms
21,768 KB
testcase_84 AC 584 ms
22,588 KB
testcase_85 AC 497 ms
21,880 KB
testcase_86 AC 27 ms
21,940 KB
testcase_87 AC 659 ms
21,992 KB
testcase_88 AC 1,015 ms
22,216 KB
testcase_89 AC 1,020 ms
22,204 KB
testcase_90 AC 52 ms
22,612 KB
testcase_91 AC 114 ms
21,904 KB
testcase_92 AC 214 ms
22,396 KB
testcase_93 AC 637 ms
22,612 KB
testcase_94 AC 797 ms
21,892 KB
testcase_95 AC 328 ms
21,892 KB
testcase_96 AC 136 ms
21,868 KB
testcase_97 AC 986 ms
22,216 KB
testcase_98 AC 1,015 ms
21,940 KB
testcase_99 AC 991 ms
22,600 KB
権限があれば一括ダウンロードができます
コンパイルメッセージ
warning: constant is never used: `MAX_MOVES`
  --> Main.rs:98:1
   |
98 | const MAX_MOVES: usize = 400;
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default

warning: 1 warning emitted

ソースコード

diff #

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;
const MAX_MOVES: usize = 400;
const DEFAULT_PROB: f64 = 1.0 - 0.2;

#[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(f64),
}

impl EdgeState {
    #[inline]
    fn prob(&self, p: f64) -> f64 {
        match self {
            EdgeState::NotEnter => DEFAULT_PROB,
            EdgeState::NoWall => 1.0 - p,
            EdgeState::MayBeWall(pi) => *pi,
        }
    }
}

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 {
    for trial in 0.. {
        let moves = dp(input, &state);

        if let Some(stop) = write_output(&moves) {
            update_state(input, &mut state, &moves[..stop], moves[stop])
        } else {
            return 1001 - trial - 1;
        }
    }

    0
}

fn dp(input: &Input, state: &State) -> Vec<usize> {
    const MAX_MOVES: usize = 100;
    let mut dp = vec![Map2d::new(vec![0.0; MAP_SIZE * MAP_SIZE], MAP_SIZE); MAX_MOVES + 1];
    let mut from = vec![Map2d::new(vec![0; MAP_SIZE * MAP_SIZE], MAP_SIZE); MAX_MOVES + 1];
    dp[0][Coordinate::new(0, 0)] = 1.0;

    for turn in 0..MAX_MOVES {
        for row in 0..MAP_SIZE {
            for col in 0..MAP_SIZE {
                let c = Coordinate::new(row, col);
                for dir in 0..4 {
                    let edge = state.map[c][dir];
                    if let Some(next) = edge.next {
                        let prob = (edge.state.prob(input.p)
                            - 1e-3 * (row as f64 - col as f64).abs())
                        .max(0.0);

                        if chmax!(dp[turn + 1][next], dp[turn][c] * prob) {
                            from[turn + 1][next] = dir;
                        }
                    }
                }
            }
        }
    }

    let mut max_prob = 0.0;
    let mut max_turn = 0;
    let goal = Coordinate::new(MAP_SIZE - 1, MAP_SIZE - 1);

    for turn in 0..=MAX_MOVES {
        if chmax!(max_prob, dp[turn][goal]) {
            max_turn = turn;
        }
    }

    let mut current = goal;
    let mut turn = max_turn;
    let mut moves = vec![];

    while turn > 0 {
        let dir = from[turn][current];
        moves.push(dir);
        current = current + ADJACENTS[dir ^ 2];
        turn -= 1;
    }

    moves.reverse();
    moves
}

fn update_state(input: &Input, 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][ng].state = match state.map[current][ng].state {
        EdgeState::NotEnter => EdgeState::MayBeWall(1.0),
        EdgeState::NoWall => EdgeState::NoWall,
        EdgeState::MayBeWall(c) => EdgeState::MayBeWall(c * input.p),
    }
}

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

#[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]
        }
    }
}
0