1349. 参加考试的最大学生数

题目描述

给一个m*n的矩阵seats表示教室内座位的分布,如果是坏的用“#”表示不能坐人
同时为了避免作弊,学生左,右,左前,右前4个位置不能有人
求给定座位后,最多能坐多少个学生?
提示:

  • 1<=m<=8
  • 1<=n<=8
f1-动态规划+状态压缩

基本分析

  1. 每一行坐人的状态怎么表示?参考给的数据规模,用二进制来表示坐人的状态
  2. 怎么满足以上的限制条件?
    • 坏的不能坐人?对某一行,预处理座位,把“#”用1代替,“.”用0代替,转化为二进制表达chair,如果chair&当前学生状态state==0,表示不冲突
    • 左右不能有人? state & (state >>1)==0 , state &(state<<1)==0
    • 左前右前不能有人?拿去前排的状态last_state, 和上面类似
  3. 怎么根据题目给出的seats表达,预处理出需要的二进制状态表达chair?
    • 增加了第0排的状态,都是0
    • 后续每排,拿到这一排坏的位置的索引,利用运算把1放到对应的位置上,这里是用到了reduce(函数,列表)方式实现
  4. 怎么定义dp状态?定义dp[i][state]表示第i排状态是state时候,前i排能坐的最大人数
  5. 怎么初始化dp状态?增加了一个第0排,chair也增加了第0排,两个可以对上。真正遍历从i=1开始,到i=m结束
  6. 怎么转移状态?dp[i][state] = max(dp[i][state], dp[i-1][last_state]+bin(state).count('1'))
  7. 怎么拿到做后的结果?max(dp[m])

代码

class Solution:
def maxStudents(self, seats: List[List[str]]) -> int:
m, n = len(seats), len(seats[0])
# 预处理坏座位
chair = [0]
for i in range(m):
tmp = reduce(lambda x, y:x| 1<<y, [0] + [j for j in range(n) if seats[i][j]=="#"])
chair.append(tmp)
mask = 1<<n
dp = [[0]*mask for _ in range(m+1)]
for i in range(1, m+1):
for state in range(mask):
if state & chair[i] == 0 and state & (state>>1) ==0 and state & (state<<1) ==0:
for last_state in range(mask):
if state & (last_state>>1) ==0 and state & (last_state<<1)==0:
dp[i][state] = max(dp[i][state], dp[i-1][last_state] + bin(state).count('1'))
return max(dp[m])

复杂度

时间:m2n2n,O(m22n)
空间:O(m2n)

总结

  1. 用二进制表示人占据座位的情况
  2. 同样用在预处理的时候用二进制表示座位的占用情况
  3. 对于以上限制条件,用二进制的运算实现
  4. 在dp的时候,对初始化dp和chair的时候,都预先留了一个空排,以便可以从上往上顺序完成
  5. 还可以自顶向下实现,见后续解题
posted @   zhangk1988  阅读(45)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示