代码随想录算法训练营第35天|背包问题基础、46. 携带研究材料(01背包二维解法)(01背包一维解法)(acm)、416. 分割等和子集

目录

0、背包问题基础

01背包

有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次 ,求解将哪些物品装入背包里物品价值总和最大

46. 携带研究材料(01背包)

题目链接:

1、题目描述

小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。

小明的行李空间为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料只能选择一次,并且只有选与不选两种选择,不能进行切割。

2、思路

非常标准的01背包问题

3、code(二维解法)

python 复制代码
M, N = map(int, input().split())
weight = list(map(int, input().split()))
value = list(map(int, input().split()))
# 横坐标是材料,纵坐标是行李容量
dp = [[0 for _ in range(N+1)] for _ in range(M)]

# dp数组, dp[i][j]代表行李箱空间为j的情况下,从下标为[0, i]的物品里面任意取,能达到的最大价值
for i in range(0,M):
    dp[i][0] = 0
for j in range(1,N+1):
    if weight[0]<=j:
        dp[0][j] = value[0]
for i in range(0,M):
    for j in range(1,N+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[M-1][N])

3-1、code(一维解法)

python 复制代码
M, N = map(int, input().split())
# M = 3 N = 2
weight = list(map(int, input().split()))
value = list(map(int, input().split()))
# dp[j]代表行李空间为j能够携带的研究材料的最大值 j = 0 1 2
dp = [0] * (N+1)
# print(dp)
for i in range(0,M): # 0 1 2 
    for j in range(N,weight[i]-1,-1): # 2 
        dp[j] = max(dp[j],dp[j-weight[i]]+value[i])
        # dp[2] = max(dp[2],dp[2-2] +...)
print(dp[N])

4、复杂度分析

1️⃣ 时间复杂度: O ( M × N ) O(M \times N) O(M×N)

2️⃣ 空间复杂度: O ( M × N ) O(M \times N) O(M×N)

416. 分割等和子集

题目链接:link

1、题目描述

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

2、思路

把01背包问题套到本题上来。

  • 背包的体积为sum / 2
  • 背包要放入的商品(集合里的元素)重量为 元素的数值,价值也为元素的数值
  • 背包如果正好装满,说明找到了总和为 sum / 2 的子集。
  • 背包中每一个元素是不可重复放入。

3、code

python 复制代码
class Solution:
    def canPartition(self, nums: List[int]) -> bool:
        # 物品重量为数值,价值为数值
        # 背包容量为总和的一半
        # 背包装满时获得的最大价值
        # 本体就是装满时(总和的一半)物品的数值和是否和背包容量一致
        if sum(nums) % 2 != 0:
            return False
        target = sum(nums) // 2
        # target = 11
        # dp[j]代表背包容量为j装的最大价值,j:0,1,2,,,,11
        dp = [0] * (target + 1)
        for i in range(len(nums)): # 物品从0,1,2,3 
            for j in range(target,nums[i]-1,-1): # 容量从11,,,,weight[0]
                dp[j] = max(dp[j],dp[j-nums[i]]+nums[i])
        if dp[target] == target:
            return True
        else:
            return False

4、复杂度分析

1️⃣ 时间复杂度: O ( n 2 ) O(n^2) O(n2)

2️⃣ 空间复杂度: O ( n ) O(n) O(n)

相关推荐
马剑威(威哥爱编程)12 分钟前
除了递归算法,要如何优化实现文件搜索功能
java·开发语言·算法·递归算法·威哥爱编程·memoization
算法萌新——134 分钟前
洛谷P2240——贪心算法
算法·贪心算法
湖北二师的咸鱼35 分钟前
专题:二叉树递归遍历
算法·深度优先
重生之我要进大厂1 小时前
LeetCode 876
java·开发语言·数据结构·算法·leetcode
KBDYD10102 小时前
C语言--结构体变量和数组的定义、初始化、赋值
c语言·开发语言·数据结构·算法
Crossoads2 小时前
【数据结构】排序算法---桶排序
c语言·开发语言·数据结构·算法·排序算法
自身就是太阳2 小时前
2024蓝桥杯省B好题分析
算法·职场和发展·蓝桥杯
孙小二写代码2 小时前
[leetcode刷题]面试经典150题之1合并两个有序数组(简单)
算法·leetcode·面试
little redcap3 小时前
第十九次CCF计算机软件能力认证-1246(过64%的代码-个人题解)
算法
David猪大卫3 小时前
数据结构修炼——顺序表和链表的区别与联系
c语言·数据结构·学习·算法·leetcode·链表·蓝桥杯