给你一个 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 或 二分图最大独立子集)的更多相关文章

  1. HDU 1565 - 方格取数(1) - [状压DP][网络流 - 最大点权独立集和最小点权覆盖集]

    题目链接:https://cn.vjudge.net/problem/HDU-1565 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32 ...

  2. 【BZOJ5010】【FJOI2017】矩阵填数 [状压DP]

    矩阵填数 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 给定一个 h*w 的矩阵,矩阵的行 ...

  3. BZOJ 2734 [HNOI2012]集合选数 (状压DP、时间复杂度分析)

    题目链接 https://www.lydsy.com/JudgeOnline/problem.php?id=2734 题解 嗯早就想写的题,昨天因为某些不可告人的原因(大雾)把这题写了,今天再来写题解 ...

  4. 洛谷$P3226\ [HNOI2012]$集合选数 状压$dp$

    正解:$dp$ 解题报告: 传送门$QwQ$ 考虑列一个横坐标为比值为2的等比数列,纵坐标为比值为3的等比数列的表格.发现每个数要选就等价于它的上下左右不能选. 于是就是个状压$dp$板子了$QwQ$ ...

  5. $HNOI2012\ $ 集合选数 状压$dp$

    \(Des\) 求对于正整数\(n\leq 1e5\),{\(1,2,3,...,n\)}的满足约束条件:"若\(x\)在该子集中,则\(2x\)和\(3x\)不在该子集中."的子 ...

  6. HDU 1565 方格取数 状压dp

    题目: 给你一个n*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取的数所在的2个格子不能相邻,并且取出的数的和最大. Input 包括多 ...

  7. 【BZOJ-2732】集合选数 状压DP (思路题)

    2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1070  Solved: 623[Submit][Statu ...

  8. [HNOI2012]集合选数 --- 状压DP

    [HNOI2012]集合选数 题目描述 <集合论与图论>这门课程有一道作业题,要求同学们求出\({1,2,3,4,5}\)的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x ...

  9. 【BZOJ-2734】集合选数 状压DP (思路题)

    2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1070  Solved: 623[Submit][Statu ...

  10. bzoj 2734: [HNOI2012]集合选数 状压DP

    2734: [HNOI2012]集合选数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 560  Solved: 321[Submit][Status ...

随机推荐

  1. 信奥生(OIER)请看,包囊初赛复赛全真模拟赛!

    luogu 动态追踪! 唠唠嗑 感谢 tyw 代理团主对比赛的贡献,但是由于我和 tyw 的关系紧张,tyw 取消了我和她的一切合作.CTFPC-3rd 的出题.宣传工作都交到了我手上,我这次亚历山大 ...

  2. 平衡树之Splay树详解

    认识 Splay树,BST(二叉搜索树)的一种,整体效率很高,平摊操作次数为\(O(log_2n)\),也就是说,在一棵有n个节点的BST上做M次Splay操作,时间复杂度为\(O(Mlog_2n)\ ...

  3. 【Java】java.util.ConcurrentModificationException

    异常提示信息: java.util.ConcurrentModificationException at java.util.LinkedHashMap$LinkedHashIterator.next ...

  4. 【SqlServer】02 SSMS工具基本使用入门

    之前的安装中除了SqlServer,还有一个SSMS管理工具 数据库的访问依赖于工具 SSMS提供了两种登陆方式: 创建用户: 删除用户: 创建数据库: 删除数据库: 创建表: 设置表的字段,字段名称 ...

  5. 【Lodop】01 Lodop手册阅读上手

    官方网站: http://www.c-lodop.com/index.html 版本:6.2.2.6 一.概述 Lodop是一款用于WEB打印开发的专业WEB打印控件 控件发布包有3个系统文件组成,主 ...

  6. 使用ChatGPT时的信息安全问题

    ChatGPT由于其在对话方面的AI性能的卓越表现已经远远超越了同类的产品,因此赢得了国际科研领域的极大重视,并且也得到了广大用户的支持,但是在人们尽情使用的时候往往忘记了关于ChatGPT的信息安全 ...

  7. Jmeter SHA512接口加密测试

    前言:最近,我遇到一些测试接口必须传入经过SHA512加密后的sign签名,并且签名有1小时时间限制,即签名不是一成不变超1小时就会过期,这导致在测试过程中就得频繁手工去更新签名.其实Jmeter是有 ...

  8. Dolphinscheduler Docker部署全攻略

    作者| 陈逸飞 Docker部署的目的是在容器中快速启动部署Apache Dolphinscheduler服务. 先决条件 docker-compose docker 使用容器单机部署Dolphins ...

  9. 新兴互联网银行搭档Apache SeaTunnel构建数据流通管道!

    当新兴互联网银行乘着数字化改革的风潮搭档数据集成平台Apache SeaTunnel,成千万上亿的数据就有了快速流通的管道.6月26日14:00,Apache SeaTunnel社区将带上企业最佳实践 ...

  10. Golang在整洁架构基础上实现事务

    前言 大家好,这里是白泽,这篇文章在 go-kratos 官方的 layout 项目的整洁架构基础上,实现优雅的数据库事务操作. 视频讲解 :B站:白泽talk,公众号[白泽talk] 本期涉及的学习 ...