大家好,我是星恒
今天的题目竟然是一道困难题目,看着就不简单,我们的目标是:理解如何做 + 学一些思路!
这次题目涉及的知识:动态规划,状态压缩(位运算)
给你一个 m * n 的矩阵 seats 表示教室中的座位分布。如果座位是坏的(不可用),就用 ‘#’ 表示;否则,用 ‘.’ 表示。学生可以看到左侧、右侧、左上、右上这四个方向上紧邻他的学生的答卷,但是看不到直接坐在他前面或者后面的学生的答卷。请你计算并返回该考场可以容纳的同时参加考试且无法作弊的 **最大 **学生人数。
学生必须坐在状况良好的座位上。
输入:seats = [["#",".","#","#",".","#"],
[".","#","#","#","#","."],
["#",".","#","#",".","#"]]
输出:4
解释:教师可以让 4 个学生坐在可用的座位上,这样他们就无法在考试中作弊。
示例 2:
输入:seats = [[".","#"],
["#","#"],
["#","."],
["#","#"],
[".","#"]]
输出:3
解释:让所有学生坐在可用的座位上。
示例 3:
输入:seats = [["#",".",".",".","#"],
[".","#",".","#","."],
[".",".","#",".","."],
[".","#",".","#","."],
["#",".",".",".","#"]]
输出:10
解释:让学生坐在第 1、3 和 5 列的可用座位上。
提示:
分析:
这道困难题,我们先说一下总体思路,然后再讨论为什么这样做:
首先,我们说一下数据的存储
0,1(0 好座位,1 坏座位)
来表示一排的情况,并使用二进制表示法表示这种情况,一共n位dp[m][2n]
来存储答案可能的所有情况的人数,1 …2n
表示一排可能出现的所有情况(因为这样可以将所有情况的二进制数表示了出来)好啦,现在我们就可以正式开始这道题
dp[m][2n]
的最后一排,求他们的最大值题解:
class Solution {
public int maxStudents(char[][] seats) {
final int m = seats.length, n = seats[0].length;
int[][] dp = new int[m + 1][1 << n];
for (int i = 1; i <= m; i++) {
int invalid = 0;
for (int j = 0; j < n; j++) {
if (seats[i - 1][j] == '#') {
invalid |= 1 << j;
}
}
for (int j = 0; j < (1 << n); j++) {
int adjacentMask = j << 1;
if ((j & invalid) != 0 || (j & adjacentMask) != 0) {
dp[i][j] = -1;
continue;
}
int theOtherAdjacentMask = j >> 1;
for (int s = 0; s < (1 << n); s++) {
if (dp[i - 1][s] == -1) {
continue;
}
if ((s & adjacentMask) != 0 || (s & theOtherAdjacentMask) != 0) {
continue;
}
dp[i][j] = Math.max(dp[i][j], dp[i - 1][s] + Integer.bitCount(j));
}
}
}
int max = 0;
for (int i = 0; i < 1 << n; i++) {
max = Math.max(max, dp[m][i]);
}
return max;
}
}