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])

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