Welcome to Subscribe On Youtube
1349. Maximum Students Taking Exam
Description
Given a m * n
matrix seats
that represent seats distributions in a classroom. If a seat is broken, it is denoted by '#'
character otherwise it is denoted by a '.'
character.
Students can see the answers of those sitting next to the left, right, upper left and upper right, but he cannot see the answers of the student sitting directly in front or behind him. Return the maximum number of students that can take the exam together without any cheating being possible.
Students must be placed in seats in good condition.
Example 1:
Input: seats = [["#",".","#","#",".","#"], [".","#","#","#","#","."], ["#",".","#","#",".","#"]] Output: 4 Explanation: Teacher can place 4 students in available seats so they don't cheat on the exam.
Example 2:
Input: seats = [[".","#"], ["#","#"], ["#","."], ["#","#"], [".","#"]] Output: 3 Explanation: Place all students in available seats.
Example 3:
Input: seats = [["#",".",".",".","#"], [".","#",".","#","."], [".",".","#",".","."], [".","#",".","#","."], ["#",".",".",".","#"]] Output: 10 Explanation: Place students in available seats in column 1, 3 and 5.
Constraints:
seats
contains only characters'.' and
'#'.
m == seats.length
n == seats[i].length
1 <= m <= 8
1 <= n <= 8
Solutions
Solution 1: State Compression + Memoization Search
We notice that each seat has two states: selectable and non-selectable. Therefore, we can use a binary number to represent the seat state of each row, where
Next, we design a function
We can enumerate all the seat selection states
- The state
cannot select seats outside ofmask ;seat - The state
cannot select adjacent seats.mask
If the conditions are met, we calculate the number of seats selected in the current row
Finally, we return
To avoid repeated calculations, we can use memoization search to save the return value of the function
The time complexity is
-
class Solution { private Integer[][] f; private int n; private int[] ss; public int maxStudents(char[][] seats) { int m = seats.length; n = seats[0].length; ss = new int[m]; f = new Integer[1 << n][m]; for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (seats[i][j] == '.') { ss[i] |= 1 << j; } } } return dfs(ss[0], 0); } private int dfs(int seat, int i) { if (f[seat][i] != null) { return f[seat][i]; } int ans = 0; for (int mask = 0; mask < 1 << n; ++mask) { if ((seat | mask) != seat || (mask & (mask << 1)) != 0) { continue; } int cnt = Integer.bitCount(mask); if (i == ss.length - 1) { ans = Math.max(ans, cnt); } else { int nxt = ss[i + 1]; nxt &= ~(mask << 1); nxt &= ~(mask >> 1); ans = Math.max(ans, cnt + dfs(nxt, i + 1)); } } return f[seat][i] = ans; } }
-
class Solution { public: int maxStudents(vector<vector<char>>& seats) { int m = seats.size(); int n = seats[0].size(); vector<int> ss(m); vector<vector<int>> f(1 << n, vector<int>(m, -1)); for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { if (seats[i][j] == '.') { ss[i] |= 1 << j; } } } function<int(int, int)> dfs = [&](int seat, int i) -> int { if (f[seat][i] != -1) { return f[seat][i]; } int ans = 0; for (int mask = 0; mask < 1 << n; ++mask) { if ((seat | mask) != seat || (mask & (mask << 1)) != 0) { continue; } int cnt = __builtin_popcount(mask); if (i == m - 1) { ans = max(ans, cnt); } else { int nxt = ss[i + 1]; nxt &= ~(mask >> 1); nxt &= ~(mask << 1); ans = max(ans, cnt + dfs(nxt, i + 1)); } } return f[seat][i] = ans; }; return dfs(ss[0], 0); } };
-
class Solution: def maxStudents(self, seats: List[List[str]]) -> int: def f(seat: List[str]) -> int: mask = 0 for i, c in enumerate(seat): if c == '.': mask |= 1 << i return mask @cache def dfs(seat: int, i: int) -> int: ans = 0 for mask in range(1 << n): if (seat | mask) != seat or (mask & (mask << 1)): continue cnt = mask.bit_count() if i == len(ss) - 1: ans = max(ans, cnt) else: nxt = ss[i + 1] nxt &= ~(mask << 1) nxt &= ~(mask >> 1) ans = max(ans, cnt + dfs(nxt, i + 1)) return ans n = len(seats[0]) ss = [f(s) for s in seats] return dfs(ss[0], 0)
-
func maxStudents(seats [][]byte) int { m, n := len(seats), len(seats[0]) ss := make([]int, m) f := make([][]int, 1<<n) for i, seat := range seats { for j, c := range seat { if c == '.' { ss[i] |= 1 << j } } } for i := range f { f[i] = make([]int, m) for j := range f[i] { f[i][j] = -1 } } var dfs func(int, int) int dfs = func(seat, i int) int { if f[seat][i] != -1 { return f[seat][i] } ans := 0 for mask := 0; mask < 1<<n; mask++ { if (seat|mask) != seat || (mask&(mask<<1)) != 0 { continue } cnt := bits.OnesCount(uint(mask)) if i == m-1 { ans = max(ans, cnt) } else { nxt := ss[i+1] & ^(mask >> 1) & ^(mask << 1) ans = max(ans, cnt+dfs(nxt, i+1)) } } f[seat][i] = ans return ans } return dfs(ss[0], 0) }
-
function maxStudents(seats: string[][]): number { const m: number = seats.length; const n: number = seats[0].length; const ss: number[] = Array(m).fill(0); const f: number[][] = Array.from({ length: 1 << n }, () => Array(m).fill(-1)); for (let i = 0; i < m; ++i) { for (let j = 0; j < n; ++j) { if (seats[i][j] === '.') { ss[i] |= 1 << j; } } } const dfs = (seat: number, i: number): number => { if (f[seat][i] !== -1) { return f[seat][i]; } let ans: number = 0; for (let mask = 0; mask < 1 << n; ++mask) { if ((seat | mask) !== seat || (mask & (mask << 1)) !== 0) { continue; } const cnt: number = mask.toString(2).split('1').length - 1; if (i === m - 1) { ans = Math.max(ans, cnt); } else { let nxt: number = ss[i + 1]; nxt &= ~(mask >> 1); nxt &= ~(mask << 1); ans = Math.max(ans, cnt + dfs(nxt, i + 1)); } } return (f[seat][i] = ans); }; return dfs(ss[0], 0); }