狀壓DP_hard_1434_每個人戴不同帽子的方案數

題目描述

在這裏插入圖片描述

思路

解法一:狀壓DP :TimeO(mn2n)Time O(mn2^n)

Reference

  • 其中 m爲 帽子數量,這裏是40,n是人數
class Solution:
    def numberWays(self, hats: List[List[int]]) -> int:
        # 讓人戴帽子的嵌套列表 -> 把帽子送人的字典
        d = {k: set() for k in range(1, 41)}
        n = len(hats)
        for i in range(n):
            for hat in hats[i]:
                d[hat].add(i)

        # 構造 dp table
        cols = 2 ** n
        # 第 0 行,沒有可用帽子時,方案數爲 0
        dp = [[0] * cols for i in range(41)]  # 41行 n列的 matrix
        # 沒有可用帽子,但又不用送帽子,方案數爲 1
        dp[0][0] = 1

        for i in range(1, 41):
            for j in range(cols):
                # 情況一:不送帽i
                dp[i][j] += dp[i - 1][j]
                # 情況二:送帽i給人k
                for k in d[i]:
                    # 當前戴帽狀態 j 中,人k需要帽子
                    if j & 1 << k != 0:
                        # 用 j ^ 1 << k 找到之前人k不戴帽子時的狀態
                        dp[i][j] += dp[i - 1][j ^ 1 << k]

        return dp[-1][-1] % (10 ** 9 + 7)
  • 調優:可以用滾動數組 將dp matrix 降維成 dp list

方法二:狀壓+dfs

class Solution:
    def numberWays(self, hats: List[List[int]]) -> int:
        L = len(hats)
        @lru_cache(typed=False, maxsize=128000000)
        def dfsp(i,person):
            if person == (2**L)-1:
                return 1
            if i == 41:
                return 0
            res = 0
            #給第i個帽子找人, i是帽子,j是人
            for j in range(L):
                # 如果這個人沒有帽子,並且可以帶這個帽子,就找下一個帽子
                if not person & (1 << j) and i in hats[j]:
                    res += dfsp(i + 1, person | (1 << j))
            # 不一定要選這個帽子,可以直接選下一個帽子
            res += dfsp(i + 1, person)
            return res
        ans = dfsp(1, 0) % 1000000007
        return ans
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章