状压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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章