classSolution:defnumberWays(self, hats: List[List[int]])->int:# 让人戴帽子的嵌套列表 -> 把帽子送人的字典
d ={k:set()for k inrange(1,41)}
n =len(hats)for i inrange(n):for hat in hats[i]:
d[hat].add(i)# 构造 dp table
cols =2** n
# 第 0 行,没有可用帽子时,方案数为 0
dp =[[0]* cols for i inrange(41)]# 41行 n列的 matrix# 没有可用帽子,但又不用送帽子,方案数为 1
dp[0][0]=1for i inrange(1,41):for j inrange(cols):# 情况一:不送帽i
dp[i][j]+= dp[i -1][j]# 情况二:送帽i给人kfor 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
classSolution:defnumberWays(self, hats: List[List[int]])->int:
L =len(hats)
@lru_cache(typed=False, maxsize=128000000)defdfsp(i,person):if person ==(2**L)-1:return1if i ==41:return0
res =0#给第i个帽子找人, i是帽子,j是人for j inrange(L):# 如果这个人没有帽子,并且可以带这个帽子,就找下一个帽子ifnot 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)%1000000007return ans