LeetCode 1349. 参加考试的最大学生数 (状压DP 或 二分图最大独立子集)
给你一个 m * n 的矩阵 seats 表示教室中的座位分布。如果座位是坏的(不可用),就用 '#' 表示;否则,用 '.' 表示。
学生可以看到左侧、右侧、左上、右上这四个方向上紧邻他的学生的答卷,但是看不到直接坐在他前面或者后面的学生的答卷。请你计算并返回该考场可以容纳的一起参加考试且无法作弊的最大学生人数。
学生必须坐在状况良好的座位上。
示例 1:

输入:seats = [["#",".","#","#",".","#"],
[".","#","#","#","#","."],
["#",".","#","#",".","#"]]
输出:4
解释:教师可以让 4 个学生坐在可用的座位上,这样他们就无法在考试中作弊。
提示
seats 只包含字符 '.' 和'#'
m == seats.length
n == seats[i].length
1 <= m <= 8
1 <= n <= 8
1. 状压DP
首先一看数据范围,一个学过状压DP的人就应该想到它……个人经验,数据范围在 10 左右的时候,就可以考虑下是不是状压DP。
用二进制的每一位去枚举一个位置是否坐了人,一行有n个座位,则一共有1<<n种情况。
dp[i][j]用来第i行状态为j的最大值,那么dp[i][j]=j状态包含1的个数+max(dp[i-1][k]) (0<=k<(1<<n) && j 和 k 都是合法状态 && j和k不存在能够相互抄袭的两个位置)
比赛时代码写的比较丑陋 写80多行……赛后参考了一下题解,使用 j&(j<<1) 来判断是否有相邻的点就比较厉害了~
AC代码(cpp)
class Solution {
int countOne(int x) {
int cnt = 0;
while(x != 0) x = x & (x - 1), cnt++;
return cnt;
}
public:
int maxStudents(vector<vector<char>>& seats) {
int n = seats.size();
int m = seats[0].size();
int st = 1 << m;
vector<vector<int>> dp(n, vector<int>(st, 0));
for (int i = 0; i < n; i++) {
int mask = 0;
for (int j = 0; j < m; j++) {
mask += seats[i][j] == '#' ? (1 << j) : 0;
}
for (int j = 0; j < st; j++) {
if (!(j & mask) && !(j & (j << 1))) {
int v = countOne(j);
if (i == 0) dp[i][j] = v;
else {
for (int k = 0; k < st; k++) {
if (!((k << 1) & j) && !((k >> 1) & j)) {
dp[i][j] = max(dp[i][j], dp[i - 1][k] + v);
}
}
}
}
}
}
int ans = 0;
for (int i = 0; i < st; i++) {
ans = max(dp[n - 1][i], ans);
}
return ans;
}
};
2. 二分图最大匹配
太久没有写过二分图已经没什么印象了,经群里大神提示,才又复习了一遍之前的博客。
此题如果把每个能抄袭的两个位置连接,求最大可以容纳的考生数就是求没内部有边的最大集合,即最大独立子集。
同时又知道二分图属性
最大独立数 = 顶点数 — 最大匹配数
那么此题转化为求二分图最大匹配。
有一点需要注意的是,匈牙利模板中,是将两个点集分开的情况下去求最大匹配的,而类似本题是没有规定哪个点属于哪个点集,
所以可以想象把每个点拆成两个点,每个点属于一个子集,这样才是最大匹配算法对应的结果。
而对于原集合来说,最大匹配答案应该 /2。
AC代码(cpp)
class Solution {
static const int N = 64;
vector<int> G[N];
bool used[N];
int match[N];
int r, c, n;
int id(int row, int col) {
return row * c + col;
}
void join(int x, int y) {
G[x].push_back(y);
G[y].push_back(x);
}
bool findPath(int u) {
for (int v: G[u]) {
if (used[v]) continue;
used[v] = true;
if (match[v] == -1 || findPath(match[v])) {
match[v] = u;
return true;
}
}
return false;
}
public:
int maxStudents(vector<vector<char>>& seats) {
r = seats.size(), c = seats[0].size(), n = r * c;
int total = 0;
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (seats[i][j] == '.') {
total++;
if (i > 0) {
if (j > 0 && seats[i - 1][j - 1] == '.') { // 左上
join(id(i, j), id(i - 1, j - 1));
}
if (j + 1 < c && seats[i - 1][j + 1] == '.') { // 右上
join(id(i, j), id(i - 1, j + 1));
}
}
if (j > 0 && seats[i][j - 1] == '.') { // 左侧
join(id(i, j), id(i, j - 1));
}
}
}
}
int matchNum = 0;
memset(match, -1, sizeof match);
for (int i = 0; i < n; i++) {
memset(used, false, sizeof used);
if (findPath(i)) ++matchNum;
}
return total - matchNum / 2;
}
};
LeetCode 1349. 参加考试的最大学生数 (状压DP 或 二分图最大独立子集)的更多相关文章
- HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]
题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...
- 【BZOJ5010】【FJOI2017】矩阵填数 [状压DP]
矩阵填数 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 给定一个 h*w 的矩阵,矩阵的行 ...
- BZOJ 2734 [HNOI2012]集合选数 (状压DP、时间复杂度分析)
题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2734 题解 嗯早就想写的题,昨天因为某些不可告人的原因(大雾)把这题写了,今天再来写题解 ...
- 洛谷$P3226\ [HNOI2012]$集合选数 状压$dp$
正解:$dp$ 解题报告: 传送门$QwQ$ 考虑列一个横坐标为比值为2的等比数列,纵坐标为比值为3的等比数列的表格.发现每个数要选就等价于它的上下左右不能选. 于是就是个状压$dp$板子了$QwQ$ ...
- $HNOI2012\ $ 集合选数 状压$dp$
\(Des\) 求对于正整数\(n\leq 1e5\),{\(1,2,3,...,n\)}的满足约束条件:"若\(x\)在该子集中,则\(2x\)和\(3x\)不在该子集中."的子 ...
- HDU 1565 方格取数 状压dp
题目: 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多 ...
- 【BZOJ-2732】集合选数 状压DP (思路题)
2734: [HNOI2012]集合选数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1070 Solved: 623[Submit][Statu ...
- [HNOI2012]集合选数 --- 状压DP
[HNOI2012]集合选数 题目描述 <集合论与图论>这门课程有一道作业题,要求同学们求出\({1,2,3,4,5}\)的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x ...
- 【BZOJ-2734】集合选数 状压DP (思路题)
2734: [HNOI2012]集合选数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1070 Solved: 623[Submit][Statu ...
- bzoj 2734: [HNOI2012]集合选数 状压DP
2734: [HNOI2012]集合选数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 560 Solved: 321[Submit][Status ...
随机推荐
- 痞子衡嵌入式:MCUXpresso IDE下在线联合调试i.MXRT1170双核工程的三种方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是MCUXpresso IDE下在线联合调试i.MXRT1170双核工程的三种方法. 两年前痞子衡写过一篇<i.MXRT1170下在 ...
- 【HbuilderX】解决苹果手机不能连接Win10问题
从微软商店上下载Itunes 只要这个Itunes能识别Iphone,HbuilderX也可以识别Iphone 如果之前已经装了其他来源下载的Iphone,先卸载掉,然后重启系统安装 另外: 还有一种 ...
- 【Windows】开放共享目录
在项目里面做数据迁移时发现,WindowsServer的多个主机可以进行磁盘共享访问 但是自己设置是灰白无法点击的 文件目录共享还是可以进行设置的 1.找到自己需要共享的目录,右键选择[属性],并找到 ...
- 【Zookeeper】02 文件系统 & 监听机制
官方文档上这么解释zookeeper,它是一个分布式服务框架,是Apache Hadoop 的一个子项目, 它主要是用来解决分布式应用中经常遇到的一些数据管理问题, 如:统一命名服务.状态同步服务.集 ...
- 切记:使用nvidia omniverse时一定要用2T的固态硬盘
最近在用nvidia omniverse时突然发现这样的一个问题,那就是这个软件实在是太太了,一个组件就4个多GB大小,如果安装几个组件后那么几十GB的硬盘就没有了,同时由于这个体积太大,因此再启动和 ...
- Chrome(Google) 浏览器安装Vue2、Vue3插件方法 (亲测有效)
1.背景 2.步骤 步骤一:下载插件 网站:https://chrome.zzzmh.cn/#/search 百度网盘下载: 链接:https://pan.baidu.com/s/1xdEK-7qVx ...
- 从论文到图谱,或许只差一个html
书接上回,在文章<论文图谱当如是:Awesome-Graphs用200篇图系统论文打个样>中,我向大家讲述了如何用图的方式思考图计算系统的演进历史,并在后续的系列文中结合Awesome-G ...
- 2023 ICPC 香港
gym 开场发现 E 是传统数据结构题很高兴,不过先跳了.F 知道相邻两段的长度差 \(\le1\),以为最终每段长度只有 \(\lfloor\frac{n}{m+1}\rfloor,\lceil\f ...
- JavaScript设计模式样例十八 —— 命令模式
命令模式(Command Pattern) 定义:请求以命令的形式包裹在对象中,并传给调用对象.调用对象寻找可以处理该命令的合适的对象,并把该命令传给相应的对象,该对象执行命令.目的:将一个请求封装成 ...
- JavaScript设计模式样例十六 —— 备忘录模式
备忘录模式(Memento Pattern) 定义:保存一个对象的某个状态,以便在适当的时候恢复对象.目的:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态.场景:数据缓存. ...