diff --git a/README.md b/README.md index ab69ea4..50cb2d0 100644 --- a/README.md +++ b/README.md @@ -728,3 +728,7 @@ Rust标准库`std::collections`提供了4种通用容器类型,包含一下8 - [不浪费原料的汉堡制作方案](src/math/number_of_burgers_with_no_waste_of_ingredients.rs) [数学] - LeetCode 1276. 不浪费原料的汉堡制作方案 + +- [参加考试的最大学生数](src/math/maximum_students_taking_exam.rs) [位运算, 数组, 动态规划, 状态压缩, 矩阵] + + - LeetCode 1349. 参加考试的最大学生数 diff --git a/images/math/maximum_students_taking_exam.jpeg b/images/math/maximum_students_taking_exam.jpeg new file mode 100644 index 0000000..104c725 Binary files /dev/null and b/images/math/maximum_students_taking_exam.jpeg differ diff --git a/src/math/maximum_students_taking_exam.rs b/src/math/maximum_students_taking_exam.rs new file mode 100644 index 0000000..6e7af39 --- /dev/null +++ b/src/math/maximum_students_taking_exam.rs @@ -0,0 +1,54 @@ +// 参加考试的最大学生数 +// https://leetcode.cn/problems/maximum-students-taking-exam +// INLINE ../../images/math/maximum_students_taking_exam.jpeg + +pub struct Solution; + +impl Solution { + pub fn max_students(seats: Vec>) -> i32 { + fn dfs( + seat: usize, + i: usize, + f: &mut Vec>, + ss: &Vec, + m: usize, + n: usize, + ) -> i32 { + if f[seat][i] != -1 { + return f[seat][i]; + } + let mut ans = 0; + for mask in 0..1 << n { + if (seat | mask) != seat || (mask & (mask << 1)) != 0 { + continue; + } + let cnt = mask.count_ones(); + if i == m - 1 { + ans = std::cmp::max(ans, cnt as i32); + } else { + let mut nxt = ss[i + 1]; + nxt &= !(mask >> 1); + nxt &= !(mask << 1); + ans = std::cmp::max(ans, cnt as i32 + dfs(nxt, i + 1, f, ss, m, n)); + } + } + f[seat][i] = ans; + ans + } + + let m = seats.len(); + let n = seats[0].len(); + let mut ss = vec![0; m]; + let mut f = vec![vec![-1; m]; 1 << n]; + + for i in 0..m { + for j in 0..n { + if seats[i][j] == '.' { + ss[i] |= 1 << j; + } + } + } + + dfs(ss[0], 0, &mut f, &ss, m, n) + } +} diff --git a/src/math/mod.rs b/src/math/mod.rs index bb0cf66..54022e9 100644 --- a/src/math/mod.rs +++ b/src/math/mod.rs @@ -17,3 +17,4 @@ pub mod circle_and_rectangle_overlapping; pub mod find_the_pivot_integer; pub mod next_greater_numerically_balanced_number; pub mod number_of_burgers_with_no_waste_of_ingredients; +pub mod maximum_students_taking_exam; diff --git a/tests/math/maximum_students_taking_exam_test.rs b/tests/math/maximum_students_taking_exam_test.rs new file mode 100644 index 0000000..9ea83fe --- /dev/null +++ b/tests/math/maximum_students_taking_exam_test.rs @@ -0,0 +1,51 @@ +use rust_practice::math::maximum_students_taking_exam::Solution; + +#[test] +fn max_students() { + // 示例 1: + // 输入:seats = [["#",".","#","#",".","#"], + //   [".","#","#","#","#","."], + //   ["#",".","#","#",".","#"]] + // 输出:4 + // 解释:教师可以让 4 个学生坐在可用的座位上,这样他们就无法在考试中作弊。 + let seats = vec![ + vec!['#', '.', '#', '#', '.', '#'], + vec!['.', '#', '#', '#', '#', '.'], + vec!['#', '.', '#', '#', '.', '#'], + ]; + assert_eq!(Solution::max_students(seats), 4); + + // 示例 2: + // 输入:seats = [[".","#"], + //   ["#","#"], + //   ["#","."], + //   ["#","#"], + //   [".","#"]] + // 输出:3 + // 解释:让所有学生坐在可用的座位上。 + let seats = vec![ + vec!['.', '#'], + vec!['#', '#'], + vec!['#', '.'], + vec!['#', '#'], + vec!['.', '#'], + ]; + assert_eq!(Solution::max_students(seats), 3); + + // 示例 3: + // 输入:seats = [["#",".",".",".","#"], + //   [".","#",".","#","."], + //   [".",".","#",".","."], + //   [".","#",".","#","."], + //   ["#",".",".",".","#"]] + // 输出:10 + // 解释:让学生坐在第 1、3 和 5 列的可用座位上。 + let seats = vec![ + vec!['#', '.', '.', '.', '#'], + vec!['.', '#', '.', '#', '.'], + vec!['.', '.', '#', '.', '.'], + vec!['.', '#', '.', '#', '.'], + vec!['#', '.', '.', '.', '#'], + ]; + assert_eq!(Solution::max_students(seats), 10); +} diff --git a/tests/math/mod.rs b/tests/math/mod.rs index 91d7b5a..54a37d8 100644 --- a/tests/math/mod.rs +++ b/tests/math/mod.rs @@ -17,3 +17,4 @@ pub mod circle_and_rectangle_overlapping_test; pub mod find_the_pivot_integer_test; pub mod next_greater_numerically_balanced_number_test; pub mod number_of_burgers_with_no_waste_of_ingredients_test; +pub mod maximum_students_taking_exam_test;