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