leetcode-位运算/状态压缩v2

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值