# 1349. Maximum Students Taking Exam
###### tags: `Leetcode` `Hard` `Dynamic Programming`
Link: https://leetcode.com/problems/maximum-students-taking-exam/
## 思路
[1411. Number of Ways to Paint N × 3 Grid](https://hackmd.io/AKffexhVRtGqAo1_PAqr2Q)的变式
每一排的排法只依赖上一排的排法 所以是一个基本型I时间序列
我们设计```dp[i][s]```表示将第```i```行安排成状态```s```时,前```i```行最多能安排多少人。```s```是一个8bit的整型数字就足以代表每一个行的策略(每个bit表示该位置是否坐人),范围就是[0,255]。对于```dp[i][s]```,我们只需要遍历所有的```dp[i-1][t]```(表示第```i-1```行安排成状态```t```的策略),查看```s```本身是否合法,以及策略```s```能否接在策略```t```后面。都满足的话,那么```dp[i][s]```及可以更新为```dp[i-1][t]+count(s)```,其中```count(s)```表示第```i```行安排策略```s```所对应的该行的人数。
## Code
```java=
class Solution {
int n;
public int maxStudents(char[][] seats) {
int m = seats.length;
n = seats[0].length;
int[][] dp = new int[m][1<<n];
// the first row of dp
for(int state=0; state<(1<<n); state++){
if(selfCheck(state, seats, 0)){
dp[0][state] = count(state);
}
}
//other rows of dp
for(int i=1; i<m; i++){
for(int state=0; state<(1<<n); state++){
if(selfCheck(state, seats, i)){
int cnt = count(state);
for(int prev=0; prev<(1<<n); prev++){
if(selfCheck(prev, seats, i-1) && checkDiffRows(state, prev)){
dp[i][state] = Math.max(dp[i][state], dp[i-1][prev]+cnt);
}
}
}
}
}
//get answer
int ans = 0;
for(int state=0; state<(1<<n); state++){
ans = Math.max(ans, dp[m-1][state]);
}
return ans;
}
private int count(int mask){
int ans=0;
for(int i=0; i<n; i++){
if(((mask>>i)&1)==1) ans++;
}
return ans;
}
private boolean selfCheck(int mask, char[][] seats, int row){
List<Integer> students = new ArrayList<>();
for(int i=0; i<n; i++){
if(((mask>>i)&1)==1) students.add(i);
}
for(int i=0; i<students.size(); i++){
if(i!=0 && students.get(i)-students.get(i-1)==1) return false;
if(seats[row][students.get(i)]=='#') return false;
}
return true;
}
private boolean checkDiffRows(int mask1, int mask2){
List<Integer> s1 = new ArrayList<>();
List<Integer> s2 = new ArrayList<>();
for(int i=0; i<n; i++){
s1.add(mask1%2);
s2.add(mask2%2);
mask1/=2;
mask2/=2;
}
for(int i=0; i<n; i++){
if(s2.get(i)==0) continue;
if(i-1>=0 && s1.get(i-1)==1) return false;
if(i+1<n && s1.get(i+1)==1) return false;
}
return true;
}
}
```