Descpition
There are n people and 40 types of hats labeled from 1 to 40.
Given a list of list of integers hats, where hats[i] is a list of all hats preferred by the i-th person.
Return the number of ways that the n people wear different hats to each other.
Since the answer may be too large, return it modulo 10^9 + 7.
Example
Input: hats = [[1,2,3],[2,3,5,6],[1,3,7,9],[1,8,9],[2,5,7]]
Output: 111
Note
n == hats.length
1 <= n <= 10
1 <= hats[i].length <= 40
1 <= hats[i][j] <= 40
hats[i] contains a list of unique integers.
分析
本题需要用状态压缩来实现,一开始希望用 dict 来存储状态以减少存储空间和计算次数。但是事与愿违。
后面改用数组来做存储
code
TLE 版本
class Solution(object):
def _do(self, hats):
hat = 0
for i in hats:
for j in i:
hat |= (1<<(j-1))
dp = [{} for _ in range(len(hats))]
bitS = lambda x: 1 << (x-1)
for v in hats[0]:
dp[0][hat ^ bitS(v)] = 1
for level in range(1, len(hats)): # 每次都会计算满足 people[i] 帽子方案,等所有 people 都有帽子戴后返回所有值
for v in hats[level]:
for k in dp[level-1]:
t, nb = k & bitS(v), k ^ bitS(v)
if t == 0:
continue
dp[level][nb] = (dp[level].get(nb, 0) + dp[level-1][k])%1000000007
return sum([i for i in dp[-1].values()])%1000000007
def do(self, hats):
print(self._do(hats))
if __name__ == '__main__':
s = Solution()
AC 版本
class Solution(object):
def _do(self, hats):
hat_set, hat_sorted = set(), []
for i, v in enumerate(hats):
hat_set |= set(v)
hat_sorted = sorted(list(hat_set))
dp = [[0 for _ in range(0, 1<<len(hats))] for _ in range(len(hat_sorted))]
bitS = lambda x: 1 << (x-1)
for i, v in enumerate(hats):
if hat_sorted[0] in v:
dp[0][bitS(i+1)] = 1
for level in range(1, len(hat_sorted)): # 每次都会计算 hat_sorted[i] 已经满足了哪些人的戴帽子需求
for person in range(0, len(hats)):
if hat_sorted[level] not in hats[person]:
continue
dp[level][bitS(person+1)] = 1
for i, v in enumerate(dp[level-1]):
if i & bitS(person+1) != 0:
continue
dp[level][i | bitS(person+1)] += v
for i, v in enumerate(dp[level-1]): # 不用当前帽子时的方案
dp[level][i] += dp[level-1][i]
return dp
def do(self, hats):
print(self._do(hats))
if __name__ == '__main__':
s = Solution()
s.do([[3,2,1],[2,3]])
总结
- 思路很简单,就是一道普通的状态压缩 dp。但是选择不用的事物作为 dp 压缩会有很大不同的结果
Runtime: 472 ms, faster than 54.46% of Python online submissions for Number of Ways to Wear Different Hats to Each Other.
Memory Usage: 13.7 MB, less than 61.46% of Python online submissions for Number of Ways to Wear Different Hats to Each Other.