From 8033e2e9a4c6ae50493ec923099a97a570960de8 Mon Sep 17 00:00:00 2001 From: jackfiled Date: Mon, 10 Feb 2025 12:12:33 +0800 Subject: [PATCH] 20250210 finished. --- src/problem/mod.rs | 2 + src/problem/p913_cat_and_mouse.rs | 171 ++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 src/problem/p913_cat_and_mouse.rs diff --git a/src/problem/mod.rs b/src/problem/mod.rs index b749940..f075518 100644 --- a/src/problem/mod.rs +++ b/src/problem/mod.rs @@ -476,3 +476,5 @@ mod p90_subsets_ii; mod p47_permutations_ii; mod p59_spiral_matrix_ii; + +mod p913_cat_and_mouse; diff --git a/src/problem/p913_cat_and_mouse.rs b/src/problem/p913_cat_and_mouse.rs new file mode 100644 index 0000000..193c83f --- /dev/null +++ b/src/problem/p913_cat_and_mouse.rs @@ -0,0 +1,171 @@ +/** + * [913] Cat and Mouse + */ +pub struct Solution {} + +// submission codes start here +use std::collections::VecDeque; + +const MOUSE_TURN: usize = 0; +const CAT_TURN: usize = 1; + +#[derive(Clone, Copy, Eq, PartialEq)] +enum Status { + DRAW, + MOUSE, + CAT, +} + +struct Gamer { + n: usize, + graph: Vec>, + // [i, j, mouse/cat] + degrees: Vec>>, + // [i, j, mouse/cat] + results: Vec>>, +} + +impl Gamer { + fn new(graph: Vec>) -> Self { + let graph = graph + .into_iter() + .map(|x| x.into_iter().map(|i| i as usize).collect::>()) + .collect::>>(); + + let n = graph.len(); + let mut degrees = vec![vec![vec![0; 2]; n]; n]; + + // 初始化每个节点的度 + for i in 0..n { + for j in 1..n { + degrees[i][j][MOUSE_TURN] = graph[i].len(); + degrees[i][j][CAT_TURN] = graph[j].len(); + } + } + + // 猫不能进入洞中 + for &node in graph[0].iter() { + for i in 0..n { + degrees[i][node][CAT_TURN] -= 1; + } + } + + Self { + n, + graph, + degrees, + results: vec![vec![vec![Status::DRAW; 2]; n]; n], + } + } + + fn search(&mut self) -> i32 { + // (mouse, cat, turn) + let mut queue = VecDeque::new(); + + // 鼠的必胜状态 + for j in 1..self.n { + self.results[0][j][MOUSE_TURN] = Status::MOUSE; + self.results[0][j][CAT_TURN] = Status::MOUSE; + + queue.push_back((0, j, MOUSE_TURN)); + queue.push_back((0, j, CAT_TURN)); + } + + // 猫的必胜状态 + for i in 1..self.n { + self.results[i][i][MOUSE_TURN] = Status::CAT; + self.results[i][i][CAT_TURN] = Status::CAT; + + queue.push_back((i, i, MOUSE_TURN)); + queue.push_back((i, i, CAT_TURN)); + } + + while let Some((mouse, cat, turn)) = queue.pop_front() { + let result = self.results[mouse][cat][turn]; + + for (last_mouse, last_cat, last_turn) in self.get_previous_states(mouse, cat, turn) { + if self.results[last_mouse][last_cat][last_turn] == Status::DRAW { + if (result == Status::MOUSE && last_turn == MOUSE_TURN) + || (result == Status::CAT && last_turn == CAT_TURN) + { + self.results[last_mouse][last_cat][last_turn] = result; + queue.push_back((last_mouse, last_cat, last_turn)); + } else { + self.degrees[last_mouse][last_cat][last_turn] -= 1; + + if self.degrees[last_mouse][last_cat][last_turn] == 0 { + self.results[last_mouse][last_cat][last_turn] = + if last_turn == MOUSE_TURN { + Status::CAT + } else { + Status::MOUSE + }; + queue.push_back((last_mouse, last_cat, last_turn)); + } + } + } + } + } + + match self.results[1][2][MOUSE_TURN] { + Status::DRAW => 0, + Status::MOUSE => 1, + Status::CAT => 2, + } + } + + // Return last (mouse, cat, turn) + fn get_previous_states( + &self, + mouse: usize, + cat: usize, + turn: usize, + ) -> Vec<(usize, usize, usize)> { + let previous_turn = if turn == MOUSE_TURN { + CAT_TURN + } else { + MOUSE_TURN + }; + + if previous_turn == MOUSE_TURN { + self.graph[mouse] + .iter() + .map(|x| (*x, cat, previous_turn)) + .collect() + } else { + self.graph[cat] + .iter() + .filter_map(|x| { + if x == &0 { + None + } else { + Some((mouse, *x, previous_turn)) + } + }) + .collect() + } + } +} + +impl Solution { + pub fn cat_mouse_game(graph: Vec>) -> i32 { + let mut gamer = Gamer::new(graph); + + gamer.search() + } +} + +// submission codes end + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_913() { + assert_eq!( + 1, + Solution::cat_mouse_game(vec![vec![1, 3], vec![0], vec![3], vec![0, 2]]) + ); + } +}