【Day30】卡码网:46. 携带研究材料,LeetCode:416. 分割等和子集

文章目录

卡码网:46. 携带研究材料

https://kamacoder.com/problempage.php?pid=1046

0-1背包问题,二维

思路

  1. 定义:dp[i][j] 表示只考虑前 i 件物品(索引从 0i ),在背包容量为 j 时能获得的最大价值。最终目标为 dp[n-1][bag]
  2. 状态转移方程:
    (1)当 j < weight[i](当前容量放不下第 i 件物品)时:
    dp[i][j] = dp[i-1][j] ,即不选第 i 件,结果与前 i - 1 件相同。
    (2)当 j >= weight[i](可以放下第 i 件物品)时:
    dp[i][j] = max(dp[i-1][j], dp[i-1][j - weight[i]] + value[i])
    不选:价值为 dp[i-1][j]
    选:先腾出 weight[i] 的空间( j - weight[i] ),加上第 i 件的价值。
  3. 初始化:所有 dp[i][j] 初始化为0。

解答

python 复制代码
first_line = input().split()
n = int(first_line[0])
bag = int(first_line[1])

second_line = input().split()
third_line = input().split()
weight = [int(x) for x in second_line]
value = [int(x) for x in third_line]

dp = [[0] * (bag + 1) for _ in range(n)]

for j in range(weight[0], bag + 1):
    dp[0][j] = value[0]

for i in range(1, n):
    for j in range(bag + 1):
        if j < weight[i]:
            dp[i][j] = dp[i - 1][j]
        else:
            dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])

print(dp[n - 1][bag])

0-1背包问题,一维

思路

  1. 定义:dp[j] 表示当前考虑的物品范围内,背包容量为 j 时能获得的最大价值。
  2. 状态转移方程:dp[j] = max(dp[j], dp[j - w] + v) (j >= w)
  3. 初始化:dp = [0] * (bag + 1)

解答

python 复制代码
first_line = input().split()
n = int(first_line[0])
bag = int(first_line[1])

second_line = input().split()
third_line = input().split()
weight = [int(x) for x in second_line]
value = [int(x) for x in third_line]

dp = [0] * (bag + 1) # dp[j] 表示容量 j 能获得的最大价值

for i in range(n):
    w = weight[i]
    v = value[i]
    # 逆序遍历,保证每种物品只选一次
    for j in range(bag, w - 1, -1):
        dp[j] = max(dp[j], dp[j - w] + v)

print(dp[bag])

LeetCode:416. 分割等和子集

https://leetcode.cn/problems/partition-equal-subset-sum/description/
添加链接描述

思路

转化为01-背包问题:每个元素只能选或不选,背包容量为 target,求是否能恰好装满。

解答

python 复制代码
class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        total = sum(nums)
        # 总和为奇数则无法平分
        if total % 2 != 0:
            return False
        
        target = total // 2
        n = len(nums)
        
        # dp[j] 表示当前已考虑的元素能否凑出和为 j
        dp = [False] * (target + 1)
        dp[0] = True
        
        for num in nums:
            # 从后往前更新,避免重复使用当前元素
            for j in range(target, num - 1, -1):
                dp[j] = dp[j] or dp[j - num]
        
        return dp[target]
相关推荐
CTA终结者4 小时前
近期AI量化工具推荐,围绕最难推进的环节选择
人工智能·python
谙忆5 小时前
Python 常用图像处理库速查:Pillow、OpenCV、rembg、pillow-simd 各擅长什么、怎么选
图像处理·python·pillow
敲代码的猴先生5 小时前
论文分享 | TensorAbuse:通过滥用TensorFlow API将AI模型转化为恶意软件
人工智能·python·语言模型·tensorflow·论文笔记
言乐65 小时前
Python视频相对亮度检测
数据库·python·计算机视觉·小程序·音视频
Csvn5 小时前
Python 开发技巧 · logging 最佳实践 —— 告别 print,搭建工程级日志系统
后端·python
ShallWeL5 小时前
【机器学习】(16)—— 数值数据
人工智能·python·算法·机器学习·数据分析
gr95ZS6E65 小时前
基础入门java安全(一)--CC1基础分析
开发语言·python
极度的坦诚就是无坚不摧5 小时前
数据分析DAY1-Python基础
python·数据分析
hongyucai5 小时前
详解rlinf强化学习四步曲
人工智能·python·算法·架构