結果

問題 No.2913 二次元距離空間
ユーザー Yukino DX.Yukino DX.
提出日時 2024-11-08 23:05:27
言語 Rust
(1.77.0 + proconio)
結果
AC  
実行時間 30 ms / 2,000 ms
コード長 3,985 bytes
コンパイル時間 15,663 ms
コンパイル使用メモリ 379,328 KB
実行使用メモリ 7,168 KB
最終ジャッジ日時 2024-11-08 23:05:45
合計ジャッジ時間 13,256 ms
ジャッジサーバーID
(参考情報)
judge5 / judge4
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
5,248 KB
testcase_01 AC 1 ms
5,248 KB
testcase_02 AC 1 ms
5,248 KB
testcase_03 AC 1 ms
5,248 KB
testcase_04 AC 1 ms
5,248 KB
testcase_05 AC 1 ms
5,248 KB
testcase_06 AC 1 ms
5,248 KB
testcase_07 AC 0 ms
5,248 KB
testcase_08 AC 1 ms
5,248 KB
testcase_09 AC 1 ms
5,248 KB
testcase_10 AC 1 ms
5,248 KB
testcase_11 AC 1 ms
5,248 KB
testcase_12 AC 1 ms
5,248 KB
testcase_13 AC 1 ms
5,248 KB
testcase_14 AC 1 ms
5,248 KB
testcase_15 AC 1 ms
5,248 KB
testcase_16 AC 9 ms
7,168 KB
testcase_17 AC 10 ms
7,040 KB
testcase_18 AC 30 ms
7,040 KB
testcase_19 AC 29 ms
7,040 KB
testcase_20 AC 30 ms
7,040 KB
testcase_21 AC 5 ms
7,040 KB
testcase_22 AC 5 ms
7,168 KB
testcase_23 AC 30 ms
7,040 KB
testcase_24 AC 5 ms
7,040 KB
testcase_25 AC 29 ms
7,168 KB
testcase_26 AC 5 ms
7,040 KB
testcase_27 AC 27 ms
7,040 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

use std::{cmp::Reverse, collections::BinaryHeap};

use proconio::{input, marker::Chars};

fn main() {
    input! {
        h:usize,
        w:usize,
        s:[Chars;h],
    }
    const INF: usize = std::usize::MAX;

    let mut dists = vec![vec![(INF, 0usize); w]; h];
    dists[0][0] = (0, 0);
    let mut pq = BinaryHeap::new();
    pq.push(Reverse((0, 0, 0)));
    while let Some(Reverse((yoko, tate, crr))) = pq.pop() {
        let (cx, cy) = (crr / w, crr % w);
        if dists[cx][cy] < (yoko, tate) {
            continue;
        }

        for Pos { x: nx, y: ny } in Pos::new(cx, cy).neigh4(h, w) {
            if s[nx][ny] == '#' {
                continue;
            }

            let dist_nxt = if cx == nx {
                (dists[cx][cy].0 + 1, dists[cx][cy].1)
            } else {
                (dists[cx][cy].0, dists[cx][cy].1 + 1)
            };
            if dist_nxt < dists[nx][ny] {
                dists[nx][ny] = dist_nxt;
                pq.push(Reverse((dist_nxt.0, dist_nxt.1, nx * w + ny)));
            }
        }
    }

    if dists[h - 1][w - 1] == (INF, 0) {
        println!("No");
    } else {
        let (ans_x, ans_y) = dists[h - 1][w - 1];
        println!("Yes");
        println!("{} {}", ans_x, ans_y);
    }
}

use grid_mgr::*;
mod grid_mgr {
    //[R,D,L,U]
    pub const DIR4: [(usize, usize); 4] = [(0, 1), (1, 0), (0, !0), (!0, 0)];
    pub const DIR8: [(usize, usize); 8] = [
        (1, 0),
        (1, !0),
        (0, !0),
        (!0, !0),
        (!0, 0),
        (!0, 1),
        (0, 1),
        (1, 1),
    ];

    pub struct Pos {
        pub x: usize,
        pub y: usize,
    }

    impl Pos {
        #[allow(dead_code)]
        pub fn new(x: usize, y: usize) -> Self {
            Self { x, y }
        }

        #[allow(dead_code)]
        pub fn neigh4<'a>(&'a self, h: usize, w: usize) -> impl Iterator<Item = Pos> + 'a {
            DIR4.iter().filter_map(move |&(dx, dy)| {
                let nx = self.x.wrapping_add(dx);
                let ny = self.y.wrapping_add(dy);
                if nx < h && ny < w {
                    Some(Pos::new(nx, ny))
                } else {
                    None
                }
            })
        }

        #[allow(dead_code)]
        pub fn neigh8<'a>(&'a self, h: usize, w: usize) -> impl Iterator<Item = Pos> + 'a {
            DIR8.iter().filter_map(move |&(dx, dy)| {
                let nx = self.x.wrapping_add(dx);
                let ny = self.y.wrapping_add(dy);
                if nx < h && ny < w {
                    Some(Pos::new(nx, ny))
                } else {
                    None
                }
            })
        }

        #[allow(dead_code)]
        pub fn line<'a>(
            &'a self,
            h: usize,
            w: usize,
            dir: (usize, usize),
        ) -> impl Iterator<Item = Pos> + 'a {
            (0..).map_while(move |i| {
                let nx = self.x.wrapping_add(dir.0.wrapping_mul(i));
                let ny = self.y.wrapping_add(dir.1.wrapping_mul(i));
                if nx < h && ny < w {
                    Some(Pos::new(nx, ny))
                } else {
                    None
                }
            })
        }

        #[allow(dead_code)]
        pub fn _moveto(&self, h: usize, w: usize, dir: (usize, usize)) -> Option<Pos> {
            let nx = self.x.wrapping_add(dir.0);
            let ny = self.y.wrapping_add(dir.1);
            if nx < h && ny < w {
                Some(Pos::new(nx, ny))
            } else {
                None
            }
        }

        #[allow(dead_code)]
        pub fn moveto(&self, h: usize, w: usize, dir: char) -> Option<Pos> {
            match dir {
                'R' => self._moveto(h, w, DIR4[0]),
                'D' => self._moveto(h, w, DIR4[1]),
                'L' => self._moveto(h, w, DIR4[2]),
                'U' => self._moveto(h, w, DIR4[3]),
                _ => unreachable!(),
            }
        }
    }
}
0