// 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>, damage: Vec>>, jewelry_num: Vec>, } impl Labyrinth { fn new() -> Self { let ndh: Vec = 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 = read_vec(); board.push(board_i); } let m: usize = read(); let mut yxd = vec![]; for _ in 0..m { let yxd_i: Vec = 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 { let mut s = String::new(); std::io::stdin().read_line(&mut s).ok(); s.trim().parse().ok().unwrap() } fn read_vec() -> Vec { read::() .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, 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 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 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 for BitSet { type Output = Self; #[inline] fn shl(mut self, x: usize) -> Self { self <<= x; self } } impl<'a> std::ops::Shl 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 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 for BitSet { type Output = Self; #[inline] fn shr(mut self, x: usize) -> Self { self >>= x; self } } impl<'a> std::ops::Shr 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)*} }; }