状态压缩dp2

题目:

给你一个 m * n 的矩阵 seats 表示教室中的座位分布。如果座位是坏的(不可用),就用 '#' 表示;否则,用 '.' 表示。

学生可以看到左侧、右侧、左上、右上这四个方向上紧邻他的学生的答卷,但是看不到直接坐在他前面或者后面的学生的答卷。请你计算并返回该考场可以容纳的一起参加考试且无法作弊的最大学生人数。

学生必须坐在状况良好的座位上。

示例 1:
输入:seats = [["#",".","#","#",".","#"],
  [".","#","#","#","#","."],
  ["#",".","#","#",".","#"]]
输出:4
解释:教师可以让 4 个学生坐在可用的座位上,这样他们就无法在考试中作弊。

解题思路:

 1 class Solution {
 2 public:
 3     int bcount(int x){ for (int ret = 0; ; x -= x&-x, ++ret) if (x == 0) return ret; }
 4     
 5     int maxStudents(vector<vector<char>>& seats) {
 6         int n = seats.size(), m = seats[0].size();
 7         int dp[n + 1][1<<m];
 8 
 9         memset(dp, -1, sizeof(dp));
10         dp[0][0] = 0;
11         
12         int lim = (1 << m);
13         for (int i = 1; i <= n; i++){
14             for (int cur = 0; cur < lim; cur++){
15                 for (int pre = 0; pre < lim; pre++){
16                     if (dp[i - 1][pre] == -1) continue; // 第 i - 1 行作为情况做 pre 的方案不存在
17                     
18                     bool flag = true;
19                     for (int j = 0; j < m; j++){
20                         if (((cur>>j)&1) == 0) continue; // 如果这个位置没人坐,不用检查了
21                         if (seats[i - 1][j] == '#') flag = false; // 有人坐,但椅子坏了
22                         if (j >= 1 && ((cur>>(j - 1))&1)) flag = false; // 有人坐,但左边有人
23                         if (j + 1 < m && ((cur>>(j + 1))&1)) flag = false; // 有人坐,但右边有人
24                         if (j >= 1 && ((pre>>(j - 1))&1)) flag = false; // 有人坐,但左前有人
25                         if (j + 1 < m && ((pre>>(j + 1))&1)) flag = false; // 有人坐,但右前有人
26                     }
27                     if (flag == false) continue;
28                     
29                     dp[i][cur] = max(dp[i][cur], dp[i - 1][pre] + bcount(cur));
30                 }
31             }
32         }
33         
34         int ans = 0;
35         for (int s = 0; s < lim; s++) ans = max(ans, dp[n][s]);
36         return ans;
37     }
38 };

 

posted @ 2021-06-30 16:40  Jinxiaobo0509  阅读(38)  评论(0)    收藏  举报