leetcode416,1049(求最大价值)474(二维01)///494(求组合类)

 

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        if sum(nums)%2==1:
            return False
        bag=sum(nums)//2#背包的体积
        dp=[0]*(bag+1)#能凑成i的最大的子集和。
        for i in range(len(nums)):
            for j in range(bag,nums[i]-1,-1):#倒序,防止物品重复加入到背包。
                dp[j]=max(dp[j],dp[j-nums[i]]+nums[i])
        return bag==dp[bag]
    '''背包的体积为sum//2
        每个数只能用一次
        价格和重量相等
        要把背包正好装满。如果能正好装满,说明找到了总和为sum//2的子集。
        dp[j]表示子集和。如果子集和恰巧等于bag的话,说明T,否则F'''


 

class Solution:
    def lastStoneWeightII(self, stones: List[int]) -> int:
        target=sum(stones)//2
        dp=[0]*(target+1)
        for i in range(len(stones)):
            for j in range(target,stones[i]-1,-1):
                dp[j]=max(dp[j],dp[j-stones[i]]+stones[i])
        return sum(stones)-2*dp[-1]
'''和416题差不多意思,这个题其实简单来讲的意思就是,我们需要划分出两个阵列,让他们比赛,尽可能的能全
消除掉,如果不能全部消除的话,就尽可能的少剩。那这就要求两边的数差不多大。所以又回到了416题的思路。
只不过最后我们需要返回差值。注意不可以返回2*(bag-dp[bag]),因为bag是sum//2出来的,这样返回永远是0'''
class Solution:
    def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
        dp=[[0 for _ in range(n+1)] for _ in range(m+1)]
        for sr in strs:
            onenum=sr.count('1')
            zeronum=sr.count('0')
            for i in range(m,zeronum-1,-1):#先遍历行,再遍历列,dp设置行是按0的size设定的。
                for j in range(n,onenum-1,-1):#遍历列。按1的size设置的。
                    dp[i][j]=max(dp[i][j],dp[i-zeronum][j-onenum]+1)
        return dp[-1][-1]
    '''二维容量限制的01背包问题。m和n相当于是背包承重。dp[i][j]相当于是0的个数是i,1的个数是j的时候
    子集的个数最多有几个。它的取法有两种,一种是取自己,另一种是取去掉这个子集的0和1的
    dp[i-zeronum][j-onenum],再加上1.因为子集的个数肯定是一个个加的。'''



 

class Solution:
    def findTargetSumWays(self, nums: List[int], target: int) -> int:
        sumnums=sum(nums)
        if (sumnums+target)%2==1 or target>sumnums:#剪枝
            return 0
        bag=(sumnums+target)//2
        dp=[0]*(bag+1)
        dp[0]=1#装满容量为0的背包有一种方法就是什么都不放。
        for i in range(len(nums)):
            for j in range(bag,nums[i]-1,-1):
                dp[j]+=dp[j-nums[i]]#求组合问题都是类似这种形式。
        return dp[-1]
    '''首先把问题转化成01背包问题,01问题是选或者不选,这题所有的数都必须选,怎么转换呢?
        既然都要选,我们可以把数分为两部分,一部分为加+,一部分为加-号的。分别记为P,N。
        P-N=target,P+N=sumnums,所以P=(sumnums+target)//2。这样就转化成了,究竟选哪几个作为
        正的。
        最后就是关于递推公式。可以写成dp[j]=dp[j-nums[i]]+dp[j],其中等号右边的dp[j]表示,
        为遍历nums[i]时的dp[j]。'''


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值