首页 > 其他分享 >【动态规划】背包问题的应用

【动态规划】背包问题的应用

时间:2023-01-09 21:47:15浏览次数:63  
标签:背包 return nums sum range 动态 规划 dp

目录

0-1背包问题

应用

应用1:Leetcode.416

题目

416.分割等和子集

分析

设 \(dp[i][j]\) 表示取前 \(i\) 个元素,可以凑成和为 \(j\) 的种类是否大于 \(0\)。同时假设,设数组 \(nums\) 的和为 \(S\) ,长度为 \(n\)。

如果 \(S\) 不能被 \(2\) 整除,那么,所有的元素肯定不能分割为等和子集。

如果 \(S\) 可以被 \(2\) 整除,那么,我们就可以将数组中的元素看出物品,背包容量为 \(S/2\),题目就可以转换为0-1背包问题,最后答案就是 \(dp[i][S/2]\) 。

边界条件

边界条件就是凑成和为零的方案,即对于任何数字都不选,它也对应一种方法,所以

\[dp[i][0] = true, \quad 0 \le i \lt n \]

状态转移

对于数组中的任意一个元素 \(nums[i]\) ,都有两种选择:

  • 如果不选择当前元素,则当前状态与 \(dp[i-1][j]\) 相同;
  • 如果选择当前元素,则当前状态与 \(dp[i - 1][j-nums[i]]\) 相同。

也就是说,我们只需要从上述两种方案中,选择一个结果为 \(true\) 的方案即可,所以,状态转移方程:

\[dp[i][j] = dp[i - 1][j] \ | \ dp[i - 1][j - nums[i - 1]], \quad nums[i - 1] \le j \le S/2 \]

代码实现

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        n = len(nums)
        _sum = sum(nums)
        if _sum % 2 != 0:
            return False
        _sum = _sum // 2
        dp = [[False for _ in range(_sum + 1)] for _ in range(n + 1)]
        for i in range(n + 1):
            dp[i][0] = True

        for i in range(1, n + 1):
            for j in range(1, _sum + 1):
                # 背包容量不足,不能装入nums[i-1]
                if j < nums[i-1]:
                    dp[i][j] = dp[i - 1][j]
                else:
                    dp[i][j] = dp[i - 1][j] | dp[i - 1][j - nums[i - 1]]
        return dp[n][_sum]

对其压缩状态,优化后的实现:

class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        n = len(nums)
        _sum = sum(nums)
        if _sum % 2 != 0:
            return False
        _sum = _sum // 2

        dp = [False] * (_sum + 1)
        dp[0] = True
        for i in range(1, n + 1):
            for j in range(_sum, 0, -1):
                if j >= nums[i - 1]:
                    dp[j] = dp[j] | dp[j - nums[i - 1]]
        return dp[_sum]

标签:背包,return,nums,sum,range,动态,规划,dp
From: https://www.cnblogs.com/larry1024/p/17038583.html

相关文章

  • nginx静态目录加上动态URL转发
    vim/data/application/nginx-1.10.3/conf/nginx.confsendfileon;#tcp_nopushon;#keepalive_timeout65;keepalive_timeout0;#gzipo......
  • SQL动态创建表,时间为表名字
    declare@sqlvarchar(1000)set@sql='createtabletb_'+convert(varchar(8),dateadd(dd,-1,getdate()),112)+'(字段内容)ON[PRIMARY]TEXTIMAGE_......
  • 动态库静态库笔记
    命名linux下,动态库以.so结尾,静态库以.a结尾libxxx.a/libxxx.sogcc链接这些库的时候使用的是该库的名字xxx而不是全称libxxx.a静态库制作和使用c静态库制作gcc-c命......
  • Redis 数据结构-简单动态字符串
    Redis数据结构-简单动态字符串 无边落木萧萧下,不尽长江滚滚来。 1、简介Redis之所以快主要得益于它的数据结构、操作内存数据库、单线程和多路I/O......
  • vue3 中动态绑定 img src 问题
    vite 官方默认的配置,如果资源文件在assets文件夹打包后会把图片名加上hash值,但是直接通过:src="imgSrc"方式引入并不会在打包的时候解析,导致开发环境可以正常引入,打包后......
  • MyBatis的动态SQL详解
    MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑。MyBatis中用于实现动态SQL的元素主要有:ifchoose(when,otherwise)trimwheresetforeach......
  • MyBatis:动态SQL
    目录动态SQL介绍搭建环境if语句WhereSetchoose语句SQL片段Foreach总结动态SQL介绍动态SQL指的是根据不同的查询条件,生成不同的Sql语句.官网描述:MyBatis的强大特......
  • 【学习笔记】动态SQL
    动态SQL1.概念动态SQL:动态SQL是MyBatis的强大特性之一。如果你使用过JDBC或其它类似的框架,你应该能理解根据不同条件拼接SQL语句有多痛苦,例如拼接时要确保不能......
  • 堆、栈、调用栈、解释型、编译型、静态类型、动态类型、弱引用、强引用 概念理解
    1、堆——存储引用数据类型;2、栈——存储基本数据类型和引用数据类型的地址;3、调用栈每次函数调用会将该函数执行上下文进行入栈操作;多个函数之间的调用,通过函数调用栈......
  • 2022年度总结 2023年度规划
    2022年计划1、完善爬虫项目;......