给你一个 m * n 的矩阵 seats 表示教室中的座位分布。如果座位是坏的(不可用),就用 '#' 表示;否则,用 '.' 表示。
学生可以看到左侧、右侧、左上、右上这四个方向上紧邻他的学生的答卷,但是看不到直接坐在他前面或者后面的学生的答卷。请你计算并返回该考场可以容纳的一起参加考试且无法作弊的最大学生人数。
学生必须坐在状况良好的座位上。
示例 1:
输入:seats = [["#",".","#","#",".","#"],
[".","#","#","#","#","."],
["#",".","#","#",".","#"]]
输出:4
解释:教师可以让 4 个学生坐在可用的座位上,这样他们就无法在考试中作弊。
示例 2:
输入:seats = [[".","#"],
["#","#"],
["#","."],
["#","#"],
[".","#"]]
输出:3
解释:让所有学生坐在可用的座位上。
示例 3:
输入:seats = [["#",".",".",".","#"],
[".","#",".","#","."],
[".",".","#",".","."],
[".","#",".","#","."],
["#",".",".",".","#"]]
输出:10
解释:让学生坐在第 1、3 和 5 列的可用座位上。
提示:
seats 只包含字符 '.' 和'#'
m == seats.length
n == seats[i].length
1 <= m <= 8
1 <= n <= 8
思路:状压DP,枚举当前行和前一行的状态(二进制表示),去掉不合法的情况,正确执行状态转移即可。
class Solution {
public int maxStudents(char[][] seats) {
int m=seats.length;
int n=seats[0].length;
int len=1<<n;
int[][] dp=new int[m][len];
for(int i=0;i<len;i++) {
int num=0;
for(int j=0;j<n;j++) {
if(((i>>j)&1)!=0) {
if(seats[0][j]=='.') num++;
else {
num=0;
break;
}
}
if(j>0 && ((i>>j)&1)==1 && ((i>>j-1)&1)==1) {
num=0;
break;
}
}
dp[0][i]=num;
}
for(int i=1;i<m;i++)
for(int j=0;j<len;j++) {
for(int k=0;k<len;k++) {
int num=0;
boolean flag=false;
for(int h=0;h<n;h++) {
int x1=(j>>h-1)&1;
int x2=(j>>h+1)&1;
int x3=(k>>h)&1;
int x4=(k>>h-1)&1;
if(h>0 && x1+x3==2 || h<n-1 && x2+x3==2 || h>0 && x3+x4==2 || seats[i][h]=='#' && x3==1)
flag=true;
if(((k>>h)&1)==1) num++;
}
if(!flag) dp[i][k]=Math.max(dp[i][k], dp[i-1][j]+num);
}
}
int ans=0;
for(int i=0;i<len;i++)
ans=Math.max(ans, dp[m-1][i]);
return ans;
}
}