結果
問題 | No.5015 Escape from Labyrinth |
ユーザー | shim0 |
提出日時 | 2023-04-16 18:03:52 |
言語 | Rust (1.77.0 + proconio) |
結果 |
RE
|
実行時間 | - |
コード長 | 18,515 bytes |
コンパイル時間 | 3,427 ms |
コンパイル使用メモリ | 173,608 KB |
実行使用メモリ | 4,500 KB |
スコア | 0 |
最終ジャッジ日時 | 2023-04-16 18:04:04 |
合計ジャッジ時間 | 7,734 ms |
ジャッジサーバーID (参考情報) |
judge12 / judge15 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | RE | - |
testcase_01 | RE | - |
testcase_02 | RE | - |
testcase_03 | RE | - |
testcase_04 | RE | - |
testcase_05 | RE | - |
testcase_06 | RE | - |
testcase_07 | RE | - |
testcase_08 | RE | - |
testcase_09 | RE | - |
testcase_10 | RE | - |
testcase_11 | RE | - |
testcase_12 | RE | - |
testcase_13 | RE | - |
testcase_14 | RE | - |
testcase_15 | RE | - |
testcase_16 | RE | - |
testcase_17 | RE | - |
testcase_18 | RE | - |
testcase_19 | RE | - |
testcase_20 | RE | - |
testcase_21 | RE | - |
testcase_22 | RE | - |
testcase_23 | RE | - |
testcase_24 | RE | - |
testcase_25 | RE | - |
testcase_26 | RE | - |
testcase_27 | RE | - |
testcase_28 | RE | - |
testcase_29 | RE | - |
testcase_30 | RE | - |
testcase_31 | RE | - |
testcase_32 | RE | - |
testcase_33 | RE | - |
testcase_34 | RE | - |
testcase_35 | RE | - |
testcase_36 | RE | - |
testcase_37 | RE | - |
testcase_38 | RE | - |
testcase_39 | RE | - |
testcase_40 | RE | - |
testcase_41 | RE | - |
testcase_42 | RE | - |
testcase_43 | RE | - |
testcase_44 | RE | - |
testcase_45 | RE | - |
testcase_46 | RE | - |
testcase_47 | RE | - |
testcase_48 | RE | - |
testcase_49 | RE | - |
testcase_50 | RE | - |
testcase_51 | RE | - |
testcase_52 | RE | - |
testcase_53 | RE | - |
testcase_54 | RE | - |
testcase_55 | RE | - |
testcase_56 | RE | - |
testcase_57 | RE | - |
testcase_58 | RE | - |
testcase_59 | RE | - |
testcase_60 | RE | - |
testcase_61 | RE | - |
testcase_62 | RE | - |
testcase_63 | RE | - |
testcase_64 | RE | - |
testcase_65 | RE | - |
testcase_66 | RE | - |
testcase_67 | RE | - |
testcase_68 | RE | - |
testcase_69 | RE | - |
testcase_70 | RE | - |
testcase_71 | RE | - |
testcase_72 | RE | - |
testcase_73 | RE | - |
testcase_74 | RE | - |
testcase_75 | RE | - |
testcase_76 | RE | - |
testcase_77 | RE | - |
testcase_78 | RE | - |
testcase_79 | RE | - |
testcase_80 | RE | - |
testcase_81 | RE | - |
testcase_82 | RE | - |
testcase_83 | RE | - |
testcase_84 | RE | - |
testcase_85 | RE | - |
testcase_86 | RE | - |
testcase_87 | RE | - |
testcase_88 | RE | - |
testcase_89 | RE | - |
testcase_90 | RE | - |
testcase_91 | RE | - |
testcase_92 | RE | - |
testcase_93 | RE | - |
testcase_94 | RE | - |
testcase_95 | RE | - |
testcase_96 | RE | - |
testcase_97 | RE | - |
testcase_98 | RE | - |
testcase_99 | RE | - |
コンパイルメッセージ
warning: unused macro definition: `input` --> Main.rs:589:14 | 589 | macro_rules! input { | ^^^^^ | = note: `#[warn(unused_macros)]` on by default warning: unused variable: `h` --> Main.rs:36:20 | 36 | let (n, d, h) = (ndh[0], ndh[1] as u32, ndh[2]); | ^ help: if this is intentional, prefix it with an underscore: `_h` | = note: `#[warn(unused_variables)]` on by default warning: field `key` is never read --> Main.rs:27:5 | 24 | struct Labyrinth { | --------- field in this struct ... 27 | key: (usize, usize), | ^^^ | = note: `#[warn(dead_code)]` on by default warning: 3 warnings emitted
ソースコード
// use bitset_fixed::BitSet; // use proconio::input; // use proconio::marker::Chars; use std::collections::VecDeque; #[derive(Debug, Clone)] struct State { is_checked: bool, jewelry_bitset: BitSet, hp: i32, prev_point: Option<(usize, usize, usize)>, } impl State { fn new() -> Self { Self { is_checked: false, jewelry_bitset: BitSet::new(500), hp: 0, prev_point: None, } } } struct Labyrinth { n: usize, start: (usize, usize), key: (usize, usize), goal: (usize, usize), board: Vec<Vec<char>>, damage: Vec<Vec<Vec<i32>>>, jewelry_num: Vec<Vec<usize>>, } impl Labyrinth { fn new() -> Self { let ndh: Vec<usize> = read_vec(); let (n, d, h) = (ndh[0], ndh[1] as u32, ndh[2]); let mut board = vec![]; for _ in 0..n { let board_i: Vec<char> = read_vec(); board.push(board_i); } let m: usize = read(); let mut yxd = vec![]; for _ in 0..m { let yxd_i: Vec<usize> = read_vec(); yxd.push((yxd_i[0], yxd_i[1], yxd_i[2])); } let mut start = (0, 0); let mut key = (0, 0); let mut goal = (0, 0); let mut jewelry_num = vec![vec![0; n]; n]; let mut num = 1; for x in 0..n { for y in 0..n { match board[x][y] { 'S' => start = (x, y), 'K' => key = (x, y), 'G' => goal = (x, y), 'J' => { jewelry_num[x][y] = num; num += 1; } _ => (), } } } let mut damage = vec![vec![vec![0; 60]; 60]; 60]; for &(y, x, step) in yxd.iter() { for i in 1..60 { if i <= x && board[x - i][y] != '#' && board[x - i][y] != 'E' { for j in (0..60).step_by(step) { damage[x - i][y][j] += d as i32; } } else { break; } } for i in 1..60 { if x + i < 60 && board[x + i][y] != '#' && board[x + i][y] != 'E' { for j in (0..60).step_by(step) { damage[x + i][y][j] += d as i32; } } else { break; } } for i in 1..60 { if i <= y && board[x][y - i] != '#' && board[x][y - i] != 'E' { for j in (0..60).step_by(step) { damage[x][y - i][j] += d as i32; } } else { break; } } for i in 1..60 { if y + i < 60 && board[x][y + i] != '#' && board[x][y + i] != 'E' { for j in (0..60).step_by(step) { damage[x][y + i][j] += d as i32; } } else { break; } } } Self { n, start, key, goal, board, damage, jewelry_num, } } } fn read<T: std::str::FromStr>() -> T { let mut s = String::new(); std::io::stdin().read_line(&mut s).ok(); s.trim().parse().ok().unwrap() } fn read_vec<T: std::str::FromStr>() -> Vec<T> { read::<String>() .split_whitespace() .map(|e| e.parse().ok().unwrap()) .collect() } fn main() { let labyrinth = Labyrinth::new(); let mut dp1 = vec![vec![vec![State::new(); 1500]; 60]; 60]; // start -> key let mut dp2 = vec![vec![vec![State::new(); 1500]; 60]; 60]; // key -> goal let mut q = VecDeque::new(); // (x, y, t, dp_type) let (start_x, start_y) = labyrinth.start; dp1[start_x][start_y][0].hp = 1500; dp1[start_x][start_y][0].is_checked = true; q.push_back((start_x, start_y, 0, 1)); while let Some((x, y, t, dp_type)) = q.pop_front() { if t + 1 == 1500 { continue; } for &(dx, dy) in &[(0, 0), (1, 0), (0, 1), (!0, 0), (0, !0)] { let new_x = x + dx; let new_y = y + dy; if new_x < labyrinth.n && new_y < labyrinth.n && labyrinth.board[new_x][new_y] != '#' && labyrinth.board[new_x][new_y] != 'E' { if dp_type == 1 { if labyrinth.board[new_x][new_y] == 'K' { if !dp2[new_x][new_y][t + 1].is_checked { dp2[new_x][new_y][t + 1].is_checked = true; q.push_back((new_x, new_y, t + 1, 2)); } let mut bitset = dp1[x][y][t].jewelry_bitset.clone(); if labyrinth.jewelry_num[x][y] > 0 { bitset.set(labyrinth.jewelry_num[x][y], true); } if dp2[new_x][new_y][t + 1].jewelry_bitset.count_ones() <= bitset.count_ones() && dp1[x][y][t].hp - labyrinth.damage[new_x][new_y][(t + 1) % 60] - 1 > 0 { dp2[new_x][new_y][t + 1].jewelry_bitset >>= 500; let a = dp1[x][y][t].jewelry_bitset.clone(); dp2[new_x][new_y][t + 1].jewelry_bitset |= &a; dp2[new_x][new_y][t + 1].jewelry_bitset.set(labyrinth.jewelry_num[new_x][new_y], true); dp2[new_x][new_y][t + 1].hp = dp1[x][y][t].hp - labyrinth.damage[new_x][new_y][(t + 1) % 60] - 1; dp2[new_x][new_y][t + 1].prev_point = Some((x, y, dp_type)); } } else { if !dp1[new_x][new_y][t + 1].is_checked { dp1[new_x][new_y][t + 1].is_checked = true; q.push_back((new_x, new_y, t + 1, 1)); } let mut bitset = dp1[x][y][t].jewelry_bitset.clone(); if labyrinth.jewelry_num[x][y] > 0 { bitset.set(labyrinth.jewelry_num[x][y] , true); } if dp1[new_x][new_y][t + 1].jewelry_bitset.count_ones() <= bitset.count_ones() && dp1[x][y][t].hp - labyrinth.damage[new_x][new_y][(t + 1) % 60] - 1 > 0 { dp1[new_x][new_y][t + 1].jewelry_bitset >>= 500; let a = dp1[x][y][t].jewelry_bitset.clone(); dp1[new_x][new_y][t + 1].jewelry_bitset |= &a; dp1[new_x][new_y][t + 1].jewelry_bitset.set(labyrinth.jewelry_num[new_x][new_y], true); dp1[new_x][new_y][t + 1].hp = dp1[x][y][t].hp - labyrinth.damage[new_x][new_y][(t + 1) % 60] - 1; dp1[new_x][new_y][t + 1].prev_point = Some((x, y, dp_type)); } } } else { // dp_type == 2 if labyrinth.board[new_x][new_y] == 'G' { dp2[new_x][new_y][t + 1].jewelry_bitset = dp2[x][y][t].jewelry_bitset.clone(); dp2[new_x][new_y][t + 1].hp = dp2[x][y][t].hp - 1; dp2[new_x][new_y][t + 1].prev_point = Some((x, y, dp_type)); } else { if !dp2[new_x][new_y][t + 1].is_checked { dp2[new_x][new_y][t + 1].is_checked = true; q.push_back((new_x, new_y, t + 1, 2)); } let mut bitset = dp2[x][y][t].jewelry_bitset.clone(); if labyrinth.jewelry_num[x][y] > 0 { bitset.set(labyrinth.jewelry_num[x][y] , true); } if dp2[new_x][new_y][t + 1].jewelry_bitset.count_ones() <= bitset.count_ones() && dp2[x][y][t].hp - labyrinth.damage[new_x][new_y][(t + 1) % 60] - 1 > 0 { dp2[new_x][new_y][t + 1].jewelry_bitset >>= 500; let a = dp2[x][y][t].jewelry_bitset.clone(); dp2[new_x][new_y][t + 1].jewelry_bitset |= &a; dp2[new_x][new_y][t + 1].jewelry_bitset.set(labyrinth.jewelry_num[new_x][new_y], true); dp2[new_x][new_y][t + 1].hp = dp2[x][y][t].hp - labyrinth.damage[new_x][new_y][(t + 1) % 60] - 1; dp2[new_x][new_y][t + 1].prev_point = Some((x, y, dp_type)); } } } } } } let (goal_x, goal_y) = labyrinth.goal; let mut best_t = 0; let mut best_score = 0; for t in 0..1500 { if best_score < dp2[goal_x][goal_y][t].jewelry_bitset.count_ones() { best_t = t; best_score = dp2[goal_x][goal_y][t].jewelry_bitset.count_ones(); } } // println!("{}", best_t); let mut output = vec![]; let mut dp_type = 2; let (mut now_x, mut now_y, mut now_t) = (goal_x, goal_y, best_t); while now_t != 0 { output.push((now_x, now_y)); if dp_type == 1 { (now_x, now_y, dp_type) = dp1[now_x][now_y][now_t].prev_point.unwrap(); } else { (now_x, now_y, dp_type) = dp2[now_x][now_y][now_t].prev_point.unwrap(); } now_t -= 1; } let mut prev_x = start_x; let mut prev_y = start_y; for &(x, y) in output.iter().rev() { let dx = x as i32 - prev_x as i32; let dy = y as i32 - prev_y as i32; prev_x = x; prev_y = y; match (dx, dy) { (-1, 0) => println!("M U"), (1, 0) => println!("M D"), (0, 1) => println!("M R"), (0, -1) => println!("M L"), (0, 0) => println!("S"), _ => unreachable!() } } } const TRUE: &bool = &true; const FALSE: &bool = &false; #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] /// Fixed sized bitset pub struct BitSet { buf: Vec<u64>, size: usize, } impl BitSet { /// Construct a new, zero bitset with specified capacity. /// This method allocates O(size) bits pub fn new(size: usize) -> BitSet { BitSet { buf: vec![0; (size + 63) / 64], size, } } /// Set i-th bit to `b` #[inline] pub fn set(&mut self, i: usize, b: bool) { assert!(i < self.size); if b { self.buf[i >> 6] |= 1 << (i & 63); } else { self.buf[i >> 6] &= !(1 << (i & 63)); } } /// Get the size of bits #[inline] pub fn size(&self) -> usize { self.size } /// Get the number of ones #[inline] pub fn count_ones(&self) -> u32 { self.buf.iter().map(|x| x.count_ones()).sum() } /// Get the number of zeros #[inline] pub fn count_zeros(&self) -> u32 { self.size as u32 - self.count_ones() } /// Faster left shift and or /// /// `bitset | (bitset << x)` #[inline] pub fn shl_or(&mut self, x: usize) { let q = x >> 6; let r = x & 63; if q >= self.buf.len() { return; } if r == 0 { for i in (q..self.buf.len()).rev() { *unsafe { self.buf.get_unchecked_mut(i) } |= *unsafe { self.buf.get_unchecked(i - q) }; } } else { for i in (q + 1..self.buf.len()).rev() { *unsafe { self.buf.get_unchecked_mut(i) } |= (unsafe { self.buf.get_unchecked(i - q) } << r) | (unsafe { self.buf.get_unchecked(i - q - 1) } >> (64 - r)); } *unsafe { self.buf.get_unchecked_mut(q) } |= unsafe { self.buf.get_unchecked(0) } << r; } self.chomp(); } /// Get inner buffer #[inline] pub fn buffer(&self) -> &[u64] { &self.buf } /// Get inner buffer with mutable reference #[inline] pub fn buffer_mut(&mut self) -> &mut [u64] { &mut self.buf } /// Set tailing bits in inner buffer whose index are greater than size to `0` #[inline] pub fn chomp(&mut self) { let r = self.size & 63; if r != 0 { if let Some(x) = self.buf.last_mut() { let d = 64 - r; *x = (*x << d) >> d; } } } } impl std::ops::Index<usize> for BitSet { type Output = bool; #[inline] fn index(&self, index: usize) -> &bool { assert!(index < self.size); [FALSE, TRUE][(self.buf[index >> 6] >> (index & 63)) as usize & 1] } } impl std::ops::ShlAssign<usize> for BitSet { #[inline] fn shl_assign(&mut self, x: usize) { let q = x >> 6; let r = x & 63; if q >= self.buf.len() { for x in &mut self.buf { *x = 0; } return; } if r == 0 { for i in (q..self.buf.len()).rev() { *unsafe { self.buf.get_unchecked_mut(i) } = *unsafe { self.buf.get_unchecked(i - q) }; } } else { for i in (q + 1..self.buf.len()).rev() { *unsafe { self.buf.get_unchecked_mut(i) } = (unsafe { self.buf.get_unchecked(i - q) } << r) | (unsafe { self.buf.get_unchecked(i - q - 1) } >> (64 - r)); } *unsafe { self.buf.get_unchecked_mut(q) } = unsafe { self.buf.get_unchecked(0) } << r; } for x in &mut self.buf[..q] { *x = 0; } self.chomp(); } } impl std::ops::Shl<usize> for BitSet { type Output = Self; #[inline] fn shl(mut self, x: usize) -> Self { self <<= x; self } } impl<'a> std::ops::Shl<usize> for &'a BitSet { type Output = BitSet; #[inline] fn shl(self, x: usize) -> Self::Output { let mut result = self.clone(); result <<= x; result } } impl std::ops::ShrAssign<usize> for BitSet { #[inline] fn shr_assign(&mut self, x: usize) { let q = x >> 6; let r = x & 63; if q >= self.buf.len() { for x in &mut self.buf { *x = 0; } return; } if r == 0 { for i in 0..self.buf.len() - q { *unsafe { self.buf.get_unchecked_mut(i) } = *unsafe { self.buf.get_unchecked(i + q) }; } } else { for i in 0..self.buf.len() - q - 1 { *unsafe { self.buf.get_unchecked_mut(i) } = (unsafe { self.buf.get_unchecked(i + q) } >> r) | (unsafe { self.buf.get_unchecked(i + q + 1) } << (64 - r)); } let len = self.buf.len(); *unsafe { self.buf.get_unchecked_mut(len - q - 1) } = unsafe { self.buf.get_unchecked(len - 1) } >> r; } let len = self.buf.len(); for x in &mut self.buf[len - q..] { *x = 0; } } } impl std::ops::Shr<usize> for BitSet { type Output = Self; #[inline] fn shr(mut self, x: usize) -> Self { self >>= x; self } } impl<'a> std::ops::Shr<usize> for &'a BitSet { type Output = BitSet; #[inline] fn shr(self, x: usize) -> Self::Output { let mut result = self.clone(); result >>= x; result } } impl<'a> std::ops::BitAndAssign<&'a BitSet> for BitSet { #[inline] fn bitand_assign(&mut self, rhs: &'a Self) { for (a, b) in self.buf.iter_mut().zip(rhs.buf.iter()) { *a &= *b; } } } impl<'a> std::ops::BitAnd<&'a BitSet> for BitSet { type Output = Self; #[inline] fn bitand(mut self, rhs: &'a Self) -> Self::Output { self &= rhs; self } } impl<'a, 'b> std::ops::BitAnd<&'b BitSet> for &'a BitSet { type Output = BitSet; #[inline] fn bitand(self, rhs: &'b BitSet) -> Self::Output { let mut result = self.clone(); result &= rhs; result } } impl<'a> std::ops::BitOrAssign<&'a BitSet> for BitSet { #[inline] fn bitor_assign(&mut self, rhs: &'a Self) { for (a, b) in self.buf.iter_mut().zip(rhs.buf.iter()) { *a |= *b; } self.chomp(); } } impl<'a> std::ops::BitOr<&'a BitSet> for BitSet { type Output = Self; #[inline] fn bitor(mut self, rhs: &'a Self) -> Self::Output { self |= rhs; self } } impl<'a, 'b> std::ops::BitOr<&'b BitSet> for &'a BitSet { type Output = BitSet; #[inline] fn bitor(self, rhs: &'b BitSet) -> Self::Output { let mut result = self.clone(); result |= rhs; result } } impl<'a> std::ops::BitXorAssign<&'a BitSet> for BitSet { #[inline] fn bitxor_assign(&mut self, rhs: &'a Self) { for (a, b) in self.buf.iter_mut().zip(rhs.buf.iter()) { *a ^= *b; } self.chomp(); } } impl<'a> std::ops::BitXor<&'a BitSet> for BitSet { type Output = Self; #[inline] fn bitxor(mut self, rhs: &'a Self) -> Self { self ^= rhs; self } } impl<'a, 'b> std::ops::BitXor<&'b BitSet> for &'a BitSet { type Output = BitSet; #[inline] fn bitxor(self, rhs: &'b BitSet) -> Self::Output { let mut result = self.clone(); result ^= rhs; result } } impl std::ops::Not for BitSet { type Output = Self; #[inline] fn not(mut self) -> Self::Output { for x in &mut self.buf { *x = !*x; } self.chomp(); self } } impl<'a> std::ops::Not for &'a BitSet { type Output = BitSet; #[inline] fn not(self) -> Self::Output { !self.clone() } } macro_rules! input { (source = $s:expr, $($r:tt)*) => { let mut iter = $s.split_whitespace(); input_inner!{iter, $($r)*} }; ($($r:tt)*) => { let mut s = { use std::io::Read; let mut s = String::new(); std::io::stdin().read_to_string(&mut s).unwrap(); s }; let mut iter = s.split_whitespace(); input_inner!{iter, $($r)*} }; }