题目描述:
给你一个 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-students-taking-exam
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
状态压缩的dp
我是没想出来,哎
class Solution {
int maxStudents(char[][] seats) {
int m=seats.length;
if(m==0) return 0;
int n=seats[0].length;
int ans=0;
int [][]dp = new int[m][1<<n];//每一行有(1<<n)-1种情况
for(int i=0;i<m;i++){
for(int j=0;j<1<<n;j++){
if(!check(j,seats,i)||!ok(j)) continue;//判断是否合法
int num=number(j);//这一行考生数量
if(i==0) dp[i][j]=num;//第一行只需要管自己这行即可
else{
for(int k=0;k<1<<n;k++){//判断j|k是否合法
if(ok(j|k)) dp[i][j]=Math.max(dp[i][j],dp[i-1][k]+num);
}
}
ans= Math.max(ans,dp[i][j]);
}
}
return ans;
}
boolean check(int k,char[][] seats,int pos){//判断该状态是否与实际情况符合,即有1的位置的座位是否坏了,坏了该状态就不行
int i=0;
while(k != 0){
int a=k%2;
if(a==1&&seats[pos][i]=='#') return false;
k/=2;
i++;
}
return true;
}
boolean ok(int p){//判断该状态是否有2个1相邻,有两个1相邻表示这个人的旁边或者左前或者右前有人,那么该状态不行
int pre=0;
while(p != 0){
int a=p%2;
if(a==1&&pre==1) return false;
if(a==1) pre=1;
else pre=0;
p/=2;
}
return true;
}
int number(int k){//计算该状态有多少个1,即这一行有多少考生
int ans=0;
while(k != 0){
int a=k%2;
if(a==1) ans++;
k/=2;
}
return ans;
}
}