結果

問題 No.3121 Prime Dance
ユーザー lumc_
提出日時 2025-04-20 14:43:01
言語 Rust
(1.83.0 + proconio)
結果
AC  
実行時間 671 ms / 2,000 ms
コード長 4,795 bytes
コンパイル時間 13,160 ms
コンパイル使用メモリ 404,352 KB
実行使用メモリ 144,640 KB
最終ジャッジ日時 2025-04-20 14:43:25
合計ジャッジ時間 20,004 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 2
other AC * 21
権限があれば一括ダウンロードができます

ソースコード

diff #

#![allow(
    dead_code,
    non_snake_case,
    unused_imports,
    unused_mut,
    unused_variables,
    while_true,
    unused_assignments,
    clippy::needless_range_loop,
    clippy::ptr_arg,
    clippy::type_complexity,
    clippy::unnecessary_cast
)]
use proconio::{
    input,
    marker::{Chars, Usize1 as usize1},
    source::line::LineSource,
};
use std::collections::{BinaryHeap, HashMap, HashSet, VecDeque};
use std::io::{BufReader, Write, stdin, stdout};
use std::mem::{swap, take};

macro_rules! mat {
    ($elem:expr; $n:expr) => {
        vec![$elem; $n]
    };
    ($elem:expr; $dim0:expr; $($dim:expr);*) => {
        vec![mat![$elem; $($dim);*]; $dim0]
    };
}

const D4X: [isize; 4] = [-1, 0, 1, 0];
const D4Y: [isize; 4] = [0, 1, 0, -1];

fn is_prime(n: usize) -> bool {
    if n < 2 {
        return false;
    }
    for i in 2..=((n as f64).sqrt() as usize) {
        if n % i == 0 {
            return false;
        }
    }
    true
}

fn find_best(mut a: usize, mut b: usize) -> Option<usize> {
    let k = a.abs_diff(b);
    if k % 2 == 1 {
        let m = a.min(b);
        let u = 2_usize.saturating_sub(m);
        a += u;
        b += u;
        if !is_prime(a) || !is_prime(b) {
            return None;
        }
        return Some(u);
    }
    let mut u = 0;
    while !is_prime(a) || !is_prime(b) {
        a += 1;
        b += 1;
        u += 1;
    }
    Some(u)
}

fn main() {
    input! {
        H: usize,
        W: usize,
        mut Sy: usize1, mut Sx: usize1,
        mut Gy: usize1, mut Gx: usize1,
        mut C: [Chars; H],
    };

    if Sx > Gx {
        Sx = W - 1 - Sx;
        Gx = W - 1 - Gx;
        for i in 0..H {
            C[i].reverse();
        }
    }
    if Sy > Gy {
        Sy = H - 1 - Sy;
        Gy = H - 1 - Gy;
        C.reverse();
    }

    // 01BFS
    let inf = 1_000_000_000;
    let mut dist = mat![inf; H; W; H * W + 1; 2];
    let mut que = VecDeque::new();
    que.push_front((Sy, Sx, 0, 0, 0));
    dist[Sy][Sx][0][0] = 0;
    while let Some((y, x, use_down, did_lr, c)) = que.pop_front() {
        if dist[y][x][use_down][did_lr] < c {
            continue;
        }
        for dir in 0..4 {
            let ny = y as isize + D4Y[dir];
            let nx = x as isize + D4X[dir];
            if ny < 0 || ny >= H as isize || nx < 0 || nx >= W as isize {
                continue;
            }
            let ny = ny as usize;
            let nx = nx as usize;
            if C[ny][nx] == '#' {
                continue;
            }
            let c_down = if D4Y[dir] == 1 { 1 } else { 0 };
            let c_right = if D4X[dir] == 1 { 1 } else { 0 };
            let use_down = use_down + c_down;
            if use_down > H * W {
                continue;
            }
            let nc = c + c_right;
            // if y == 0 && x == 0 && c == 0 && use_down == 1 {
            //     dbg!(ny, nx, nc, c_down);
            //     dbg!(dist[ny][nx][use_down]);
            // }
            let n_did_lr = did_lr.max(c_right);
            if dist[ny][nx][use_down][n_did_lr] > nc {
                dist[ny][nx][use_down][n_did_lr] = nc;
                if c_right == 0 {
                    que.push_front((ny, nx, use_down, n_did_lr, nc));
                } else {
                    que.push_back((ny, nx, use_down, n_did_lr, nc));
                }
            }
        }
    }

    let mut ans = inf;
    for u_d in 0..=H * W {
        for did_lr in 0..=1 {
            let u_r = dist[Gy][Gx][u_d][did_lr];
            if u_r == inf {
                continue;
            }
            if u_r < (Gx - Sx) {
                continue;
            }
            if u_d < (Gy - Sy) {
                continue;
            }
            let u_l = u_r - (Gx - Sx);
            let u_u = u_d - (Gy - Sy);
            let mut cur = u_d + u_r + u_l + u_u;
            // if u_d == 1 {
            //     dbg!(cur);
            //     dbg!((u_d, u_u, u_r, u_l));
            //     dbg!(find_best(0, 2));
            // }
            match find_best(u_d, u_u) {
                Some(u) => {
                    if u > 0 && u_d == 0 && u_u == 0 {
                        continue;
                    }
                    cur += u * 2;
                }
                None => {
                    continue;
                }
            }
            match find_best(u_r, u_l) {
                Some(u) => {
                    if u > 0 && u_l == 0 && u_r == 0 {
                        continue;
                    }
                    cur += u * 2;
                }
                None => {
                    continue;
                }
            }
            ans = ans.min(cur);
        }
    }
    if ans == inf {
        println!("-1");
    } else {
        println!("{}", ans);
    }
}
0