leetcode-位运算/状态压缩_林冲风雪山神庙的博客-CSDN博客_leetcode 状态压缩
1239. 串联字符串的最大长度
01背包问题+状压
# leetcode submit region begin(Prohibit modification and deletion)
class Solution:
def maxLength(self, arr: List[str]) -> int:
def dfs(state,index):
if index > len(arr)-1:
return 0
word = arr[index]
#把cur放到state上,如果state 有 cur里的某个字母了,就跳过
flag = True
state_new = state
for ch in word:
#如果当前字母在state_new里,这个字母就不能加上
if state_new & (1 << (ord(ch) - ord("a"))):
flag = False
break
else:
state_new = state_new | (1 << (ord(ch) - ord("a")))
a1,a2 = 0,0
if flag == True:
a1 = dfs(state_new,index+1) + len(word)
a2 = dfs(state,index+1)
return max(a1,a2)
return dfs(0,0)
691. 贴纸拼词
完全背包+状压
class Solution:
def minStickers(self, stickers: List[str], target: str) -> int:
#state表示target的状态
m = len(target)
from collections import Counter
@lru_cache(None)
def dfs(mask):
#当所有位置为0的时候,说明target全为0了
if mask == 0:
return 0
res = m + 1
for sticker in stickers:
left = mask
sticker_count = Counter(sticker)
for i, c in enumerate(target):
#如果mask的第i位是1,并且当前贴纸包含这个字母
if mask & (1 << i) and sticker_count[c]:
sticker_count[c] -= 1
#把mask的第i位设置为0。当前贴纸可以组成target的哪位
left ^= 1 << i
#如果当前贴纸可以被选中
if left < mask:
res = min(res, dfs(left) + 1)
return res
#比如m等于15,那这个就是把15位全设置为1
res = dfs((1 << m) - 1)
return res if res <= m else -1
2305. 公平分发饼干
枚举子集
# 枚举子集(78)。看当前子集是不是可以满足条件的(用状态压缩来判断)
不同点是,这个
for i in range(1,1 << n): 要从1开始,因为不包含空子集。78题是包含空子集的。
class Solution:
def distributeCookies(self, cookies: List[int], k: int) -> int:
@lru_cache(None)
def dfs(state,max_sum,count):
if count == k:
if state == (1<<n)-1:
return True
else:
return False
flag = False
#枚举剩下的其他子集
for i1 in range(1,1 << n):
#跳过已经有过,或者有交叉的子集
if i1 & state != 0:
continue
this_sum = 0
for j1 in range(n):
if (i1 >> j1) & 1:
this_sum += cookies[j1]
if this_sum <= max_sum:
flag |= dfs(i1|state,max_sum,count+1)
return flag
# return False
n = len(cookies)
res = float("inf")
for i in range(1,1 << n):
cur_sum = 0
for j in range(n):
if (i >> j) & 1:
cur_sum += cookies[j]
if dfs(i, cur_sum, 1):
res = min(res, cur_sum)
return res
01背包枚举
class Solution:
def distributeCookies(self, cookies: List[int], k: int) -> int:
@lru_cache(None)
def dfs(state,n,c):
if c == k+1:
if state == (1 << len(cookies)) - 1:
return 0
else:
return float("inf")
res = float("inf")
for i in range(len(cookies)):
if state & (1 << i) == 0:
#放到当前k里,下一个还继续赛k桶
res = min(res,dfs(state | (1 << i), n + cookies[i], c))
#放到当前k里,下一个开始放到k+1.记录k的值为最大值
res = min(res, max(dfs(state | (1 << i), 0, c+1),n + cookies[i]))
return res
return dfs(0,0,1)