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 ...
随机推荐
- Jetpack Compose学习(12)——Material Theme的主题色切换
原文:Jetpack Compose学习(12)--Material Theme的主题色切换-Stars-One的杂货小窝 闲着无事研究了下Jetpack Compose M3 主题切换效果 本系列以 ...
- 《Programming from the Ground Up》阅读笔记:p88-p94
<Programming from the Ground Up>学习第5天,p88-p94总结,总计7页. 一.技术总结 1.touppercase.s #PURPOSE: This pr ...
- systempath:Python开发者必备的文件与系统路径操作神器!
systempath - 专业级的文件与系统路径操作库 English | 中文 systempath 是一个专为Python开发者设计的,高度专业化的文件与系统路径操作库.通过提供一套直观且功能强大 ...
- 【Java】利用反射更改String的字符
问题: 在不改变s变量引用的String对象的情况下,输出打印"abcd" /*** * * @param args * @return void * @author cloud9 ...
- 【Java】Input,Output,Stream I/O流 01 概述 & 4个基础流
Input,Output,Stream IO流 I/O Input/Output缩写.I/O技术用于处理设备之间的数据传输,读写文件,网络通讯 Java程序对于数据的操作以Stream流的形式进行 i ...
- 【Java,IDEA】创建自己的代码模版快速生成
写原生JavaWeb发现一个问题就是声明方法的时候没有字符关联提示, 只能一个保留字,一个保留字这样单个的敲出来方法,写多了就会发现特别费劲 当遇上一个字特别多且经常需要声明的方法可以使用IDEA的生 ...
- 如何在 Ubuntu18.04 server 服务器版本的操作系统下 配置IP
如题,现有需求,为一个server版本的Ubuntu18.04配置 IP . 在网上查到了 Ubuntu18.04 桌面版本 的配置方法: https://www.cnblogs.com/ ...
- Temperature 题解
前言 题目链接:洛谷:SPOJ:Hydro & bzoj. 题意简述 有一个长度为 \(n\) 的序列,每个位置值的范围为 \([L_i, R_i]\) 内,求原序列可能的最长不降子串长度. ...
- Python-目标检测-将xml文件转换成.txt文件
代码说明:labels文件夹是工程下的一个文件夹,里面存放的是一些xml文件. 然后我们将这些xml文件中的内容取出来,放在路径path1的文件名下.这样也就完成了xml文件到txt文件的转化. 该代 ...
- milvus 结果
milvus (2.3.3) 两个查询方法 collection.query(...) 和 collection.search(...) 的返回类型是不同的,用错了会说 attribute error ...