LeetCode 1349. Maximum Students Taking Exam(状压dp)

题目链接

题意:

让你给学生安排座位,有’#'号的不能坐,每个学生能看到左右和左上右上四个方向的人的试卷,请你给学生们安排座位使得学生人数最多

思路

经典的状态压缩dp问题,观察到n和m最大只有8,很明显可以利用二进制来确定第一行的状态,只要第一行定了剩下几行也就定的,最后维护最一行的最大值即可。
dp[i][j]dp[i][j]表示第ii为第jj个状态时的最大值,状态转移方程如下:
dp[i][j]=max(dp[i][j],dp[i1][k]+numofone[j])dp[i][j] = max(dp[i][j], dp[i-1][k] + num-of-one[j])
需要注意的是要提前处理好每一行不能坐的位置。

class Solution:
    def CountBinary(self, num):
        _ = 0
        while num:
            if num & 1:
                _ += 1
            num = num >> 1
        return _
    def maxStudents(self, seats: List[List[str]]) -> int:
        m, n = len(seats), len(seats[0])
        mp = [0]*m
        for i in range(m):
            for j in range(n):
                if seats[i][j] == '#':
                    mp[i] += (1 << j)
        num = []
        sta = []
        for i in range(2**n):
            if not ((i & (i << 1)) and (i & (i >> 1))):
                num.append(self.CountBinary(i))
                sta.append(i)
        dp = [[0]*(2**n) for i in range(m)]
        for i in range(len(num)):
            if not (sta[i] & mp[0]):
                dp[0][sta[i]] = num[i]
        for i in range(1, m):
            for j in range(len(num)):
                if sta[j] & mp[i]:
                    continue
                #if sta[j] & (sta[j] >> 1) and sta[j] & (sta[j] << 1):
                #    continue
                for k in range(len(num)):
                    if sta[k] & mp[i - 1]:
                        continue
                    if (sta[j] & (sta[k] >> 1)) or (sta[j] & (sta[k] << 1)):
                        continue
                    dp[i][sta[j]] = max(dp[i][sta[j]], dp[i - 1][sta[k]] + num[j])
        return max(dp[-1])

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章