[leetcode周赛] 1349. 参加考试的最大学生数
解题思路
把seats
里好座位用1
表示,坏座位用0
表示,那么每行都是一个二进制串,这个二进制串可以用一个对应的数(这里用十进制)来存储
bitSeats[i]
:
[["#",".","#","#",".","#"], //0 1 0 0 1 0 -> bitSeats[0] = 18[".","#","#","#","#","."], //1 0 0 0 0 1 -> bitSeats[1] = 33["#",".","#","#",".","#"]] //0 1 0 0 1 0 -> bitSeats[2] = 18
定义:
m = seats.size()
,行数;n = seats[0].size()
列数。
那么每行座为的情况都可以用[0,2^n - 1]
里的一个数来表示。
当n = 8
,右边为每行座位的情况,左边为十进数
0 : 00000000
1 : 00000001
2 : 00000010
3 : 00000011
4 : 00000100
5 : 00000101
6 : 00000110
7 : 00000111
8 : 00001000
9 : 00001001
10 : 00001010
11 : 00001011
12 : 00001100
13 : 00001101
14 : 00001110
15 : 00001111
16 : 00010000
17 : 00010001
18 : 00010010
19 : 00010011
20 : 00010100
21 : 00010101
22 : 00010110
23 : 00010111
......省略若干行
246 : 11110110
247 : 11110111
248 : 11111000
249 : 11111001
250 : 11111010
251 : 11111011
252 : 11111100
253 : 11111101
254 : 11111110
255 : 11111111
cnt1[i]
:存储i
对应二进制里多少个位为1
。
dp[i][j]:表示第i
行在为j
对应二进制的那种坐人方法时前i
行最大坐学生数。
对于这段代码:
for(int j = 0; j < (1<<n); j++)
这个循环遍历2^n
次,它要找到一些坐法,满足:
1).(j & curRow) == j
这种坐法是第i
行好位置的子集,就是位置是这样1100
,你只能是1000
,0100
,0000
,1100
(这个违反下一条),不能1110
这种没好位置也坐。
2).!(j & (j >> 1))
,不能出现两个人挨着坐
2.for(int k = 0; k < (1<<n); k++) 这个循环也遍历 2^n
次,作用是当第i
(curRow
)行为j
对应二进制的那种坐人方法时,在第i-1
行(curRow
的上一行)找不和它冲突的一些坐法k
,来更新dp[i][j]
,即第i
行在为j
对应二进制的那种坐人方法时前i
行最大坐学生数.
更新的状态转移方程是:dp[i][j] = max(dp[i][j], dp[i-1][k] + cnt1[j]);
k
得满足:
1. dp[i - 1][k] != -1
,第i-1
行k
坐法合法
2. !((j >> 1) & k)
:第i
行j
坐法不能有学生坐当第i-1
行为k
坐法时的合法学生左上角
3. !((j >> 1) & k)
:不能右上角
代码
class Solution {public:int maxStudents(vector<vector<char>>& seats) {int m = seats.size(), n = seats[0].size();vector<int>bitSeats(m,0); for(int i = 0; i < m; i++){int curRow = 0;for(int j = 0; j < n; j++){curRow = curRow * 2 + (seats[i][j] == '.');}bitSeats[i] = curRow;}vector<int>cnt1( 1<<n, 0);for(int i = 1; i < (1<<n); i++) cnt1[i] = cnt1[i>>1] + (i&1);//`i`与`i>>1`位为1的个数就相差一(被右移移出的那位为1时) vector<vector<int>>dp(m+1, vector<int>(1<<n, -1));dp[0][0] = 0;for(int i = 1; i <= m; i++){int curRow = bitSeats[i-1];for(int j = 0; j < (1<<n); j++){if ((j & curRow) == j && !(j & (j >> 1))){for(int k = 0; k < (1<<n); k++){if (dp[i - 1][k] != -1 && !(j & (k >> 1)) && !((j >> 1) & k)){dp[i][j] = max(dp[i][j], dp[i-1][k] + cnt1[j]);}}}}}return *max_element(dp[m].begin(), dp[m].end());}
};
建议参考这个:
https://leetcode.com/problems/maximum-students-taking-exam/discuss/503686/A-simple-tutorial-on-this-bitmasking-problem
[leetcode周赛] 1349. 参加考试的最大学生数相关推荐
- LeetCode #1349. 参加考试的最大学生数 - 学到了:压缩状态动态规划、位运算、reduce()、str().count()
赛题见:https://leetcode-cn.com/problems/maximum-students-taking-exam/ 我的解法是用递归实现广度优先搜索,结果是对的,但是太慢,超时了.这 ...
- mysql统计没有参加考试的学生名单_sQL SERVER,帮我编写一个存储过程,查询没有参加考试的学生名单,要求显示姓名、学号,具体请补充:...
--学生表CREATETABLEmember(midchar(10)primarykey,mnamechar(50)notnull,);--课程表CREATETABLEcourse(fidchar(1 ...
- 某班期末考试科目为数学(MT)、英语(EN)和物理(PH),有最多不超过40人参加考试。请编程计算:(1)每个学生的总分和平均分;(2)每门课程的总分和平均分。
某班期末考试科目为数学(MT).英语(EN)和物理(PH),有最多不超过40人参加考试.请编程计算:(1)每个学生的总分和平均分:(2)每门课程的总分和平均分. **输入格式要求:"%d&q ...
- 1、某班期末考试科目为数学(MT)、英语(EN)和物理(PH),有最多不超过30人参加考试。考试后要求:(1)计算每个学生的总分和平均分;(2)按总分成绩由高到低排出成绩的名次;(3)打印出名
#include<iostream> #include<iomanip> using namespace std; int main() { int a[30][6], ...
- 多表查询_未参加考试的学生_学生成绩档_case when then else end
sql表 班级表class 学生表student 成绩表scores 1:查询没有参加考试(没有成绩表)的学生 SELECT s.sid,s.sname,s.sex,c.cname,sc.langua ...
- 第一次LeetCode周赛心得(力扣-cn周赛,使用python3)
第一次力扣参赛:第 174 场力扣周赛 第 174 场力扣周赛赛题: https://leetcode-cn.com/circle/discuss/lEfEkb/view/OrAJAh/ 第 174 ...
- 我也是LeetCode周赛“三道题选手”啦 第270场周赛
第270场周赛小结 我的Weekly Contest 270战况 什么是LeetCode周赛? show my code! 复盘解决Hard题 我的Weekly Contest 270战况 参加周赛有 ...
- 完成以下程序,并进行调试某班期末考试科目为数学、英语和计算机,有最多不超过30人参加考试。
完成以下程序,并进行调试 某班期末考试科目为数学.英语和计算机,有最多不超过30人参加考试,考试后要求:1)计算每个学生的总分和平均分: 2)按总分成绩由高到低排出成绩的名次: 3)打印出名次表,表格 ...
- 2021年河南省高考数据统计:河南省参加考试人数占报名人数的83.7%,本土156所高校(1所211大学)
依据河南日报信息,2021年河南省高考报名人数125万人(含参加高职单招已录取20.4万人),占全国报名人数的11.6%,实际参加考试104.6万人(含专升本省统考18.74万人.对口招生省统考6.9 ...
最新文章
- java负数右移_收入囊中篇---Java程序基础(二)
- 刚刚,阿里开源了一系列重磅技术炸弹!| 程序员必看
- servlet的注解开发
- replace使用案例--替换空格
- C++学习笔记-DLL中动态内存管理
- 语句乎?表达式乎?(Python/C)
- Atitit 综合原则 软件与项目开发中的理念信念 目录 1.1. 建议组合使用扬长避短	1 1.2. 常见数据库 mysql oracle mssql mongodb postgre sqlit
- 面试2年经验的Java程序员面试题部分带答案
- PHP图片与文字合成
- 计算机信息安全专业代码0839,全国网络空间安全学科专业分布
- 【转】S60 V3 常见问题解决方法...
- 流光快门Matlab,华为手机流光快门太好玩了!这几个特效分分钟拍出大片感
- 苹果将数据转存至中国服务器 或威胁国内信息安全
- 又一家美业SaaS+系统宣布停止服务,美业人你怎么看?
- Codeforces Round #644 (Div. 3) H.Binary Median
- docker项目切换(nginx)、重启shell 脚本
- 三维声场(虚拟3D音频)学习总结(1):基本概念
- 用matlab实现高斯信道建模
- 《瓦尔登湖》中的“访客”篇中一首小诗与刘禹锡的《陋室铭》
- 牛客网刷题笔记-SQL66 牛客每个人最近的登录日期(一)
热门文章
- python从入门到精通pdf清华大学出版社-python从入门到精通 清华大学出版社
- 怎样学好python编程-3个月学好Python有多简单?
- python 入门基础-如何学习Python,以及新手如何入门?
- python和java学哪个好-python和java自学哪个好?
- micropython入门教程-【ESP8266】MicroPython的快速入门教程
- python能做什么程序-python都能做什么
- python怎么读取excel-python怎么读取excel中的数值
- 如何自学python-小白是如何自学Python逆袭成功的?
- Vue前端路由~满满的干货
- ES6数组的扩展~超详细、超好理解哦