From 106c81d7a35c457eb5a4dca2aa799d81b75a580a Mon Sep 17 00:00:00 2001 From: yenru0 Date: Thu, 12 Mar 2026 00:54:40 +0900 Subject: [PATCH] complete 28311.rs --- storage/zeta/rs/completed/28311.rs | 159 +++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 storage/zeta/rs/completed/28311.rs diff --git a/storage/zeta/rs/completed/28311.rs b/storage/zeta/rs/completed/28311.rs new file mode 100644 index 0000000..ac662d8 --- /dev/null +++ b/storage/zeta/rs/completed/28311.rs @@ -0,0 +1,159 @@ +use std::{collections::VecDeque, io::stdin, iter::zip, usize}; + +fn next_line(line: &mut String) { + line.clear(); + stdin().read_line(line).unwrap(); +} + +fn line_to_iter(line: &String) -> impl Iterator + '_ { + line.trim_ascii_end() + .split(' ') + .map(|x| x.parse::().unwrap()) +} + +const DELTAS: [(isize, isize); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)]; + +fn get_cost_field( + r: usize, + c: usize, + pos: (usize, usize), + field: &Vec>, +) -> Vec> { + let mut deq = VecDeque::new(); + + deq.push_back(((pos.0, pos.1), 0)); + + let mut cost_field = vec![vec![usize::MAX; c]; r]; + + while !deq.is_empty() { + let ((curr_r, curr_c), curr_cost) = deq.pop_front().unwrap(); + + if cost_field[curr_r][curr_c] == usize::MAX { + cost_field[curr_r][curr_c] = curr_cost; + } else { + continue; + } + for &(dr, dc) in DELTAS.iter() { + let (nxt_r, nxt_c) = (curr_r as isize + dr, curr_c as isize + dc); + if nxt_r < 0 || nxt_r >= r as isize { + continue; + } + if nxt_c < 0 || nxt_c >= c as isize { + continue; + } + let (nxt_r, nxt_c) = (nxt_r as usize, nxt_c as usize); + if field[nxt_r][nxt_c] == 'W' { + continue; + } + deq.push_back(((nxt_r, nxt_c), curr_cost + 1)); + } + } + cost_field +} + +fn solve( + r: usize, + c: usize, + dest_r: usize, + dest_c: usize, + field: &Vec>, + poses: &Vec<(usize, usize)>, +) -> (usize, usize) { + let dst_cost_field = get_cost_field(r, c, (dest_r, dest_c), field); + let pos_cost_fields = poses + .iter() + .map(|&pos| get_cost_field(r, c, pos, field)) + .collect::>(); + + let orig_values = poses + .iter() + .map(|&(r, c)| dst_cost_field[r][c]) + .collect::>(); + let orig_res = orig_values.iter().sum::(); + let mut value_sum = 0; + + for i in 0..r { + for j in 0..c { + if field[i][j] == 'W' { + let cands = DELTAS + .iter() + .map(|&(dr, dc)| (i as isize + dr, j as isize + dc)) + .filter(|&(nxt_r, nxt_c)| { + nxt_r >= 0 + && nxt_r < r as isize + && nxt_c >= 0 + && nxt_c < c as isize + && field[nxt_r as usize][nxt_c as usize] != 'W' + }) + .map(|x| (x.0 as usize, x.1 as usize)) + .collect::>(); + if cands.len() <= 1 { + continue; + } + + // + + let min_from_dst = cands + .iter() + .map(|&(nr, nc)| dst_cost_field[nr][nc]) + .min() + .unwrap(); + + if min_from_dst == usize::MAX { + continue; + } + let min_from_poses = pos_cost_fields + .iter() + .map(|f| cands.iter().map(|&(nr, nc)| f[nr][nc]).min().unwrap()); + + let rep_value = zip(&orig_values, min_from_poses) + .into_iter() + .map(|(&ov, mv)| ov.min(mv + min_from_dst + 2)) + .sum::(); + + if rep_value < orig_res { + let rep_delta = orig_res - rep_value; + value_sum += rep_delta; + } + } + } + } + (orig_res, value_sum) +} + +fn main() { + let mut line = String::new(); + next_line(&mut line); + let t = line.trim_ascii_end().parse::().unwrap(); + (0..t).for_each(|_| { + next_line(&mut line); + let (r, c, n, dest_r, dest_c) = { + let mut iter = line_to_iter(&line); + ( + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap(), + iter.next().unwrap() - 1, + iter.next().unwrap() - 1, + ) + }; + + let poses = (0..n) + .map(|_| { + next_line(&mut line); + let mut iter = line_to_iter(&line); + (iter.next().unwrap() - 1, iter.next().unwrap() - 1) + }) + .collect::>(); + + let field = (0..r) + .map(|_| { + next_line(&mut line); + line.trim_ascii_end().chars().collect::>() + }) + .collect::>(); + + let (orig_res, value_sum) = solve(r, c, dest_r, dest_c, &field, &poses); + println!("{} {}", orig_res, value_sum); + }); +}