題目描述:
給你一個 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;
}
}