首页 > 其他分享 >4、背包问题(动态规划)(递归,回溯,迭代)

4、背包问题(动态规划)(递归,回溯,迭代)

时间:2024-12-04 09:04:59浏览次数:7  
标签:背包 capacity 迭代 递归 weights 回溯 物品 values dp

一、递归,回溯,迭代 

在开始回溯算法前,我想先弄清这三个的关系 

递归是指一个函数在定义中直接或间接地调用自身,递归表现为调用函数本身,通过将问题分解为子问题来逐步解决。

回溯算法会在搜索过程中尝试一个方案,如果发现当前方案无法满足要求,就“回退”到上一个步骤,尝试其他方案。

迭代是利用循环语句实现,而循环,单纯是实现反复执行某个功能,以减少重复书写通常是while,for循环

二、背包问题

完全背包问题和 0-1 背包问题的主要区别在于,在完全背包问题中,每个物品可以选择放入背包多次(而不是一次)。

完全背包: 

完全背包问题中,每个物品可以被选择多次。

完全背包问题 中,dp[w] 表示的是背包容量为 w能得到的最大价值,并且每个物品可以被选择多次。对于每个物品 i,我们都会尝试多次将该物品放入背包,不会受到只能选择一次的限制。所以我们不需要区分物品的层级

def knapsack_complete(weights, values, capacity):
    n = len(weights)
    # 初始化DP表
    dp = [0] * (capacity + 1)

    # 填充DP表
    for i in range(n):  # 遍历每个物品
        for w in range(weights[i], capacity + 1):  # 当前容量从 weights[i] 开始
            dp[w] = max(dp[w], dp[w - weights[i]] + values[i])

    # dp[capacity] 是最大价值
    return dp[capacity]

weights = [1, 2, 3]  # 物品的重量
values = [6, 10, 12] # 物品的价值
capacity = 5         # 背包容量
print(knapsack_complete(weights, values, capacity))  # 输出: 30

01背包:

0-1背包问题中,每个物品只能选一次,要么选,要么不选。

dp[i - 1][w]表示的是考虑前 i 个物品(最后一个物品放不进去,不放),背包容量为w时能得到的最大价值。

dp[i - 1][w - weights[i - 1]] + values[i - 1]表示的是(最后一个物品能放进去)得到的最大价值

def knapsack_01(weights, values, W):
    n = len(weights)
    # 创建一个二维DP数组,dp[i][w]表示前i个物品,背包容量为w时的最大价值
    dp = [[0] * (W + 1) for _ in range(n + 1)]
    
    # 填充DP表格
    for i in range(1, n + 1):
        for w in range(1, W + 1):
            if weights[i - 1] <= w:
                # 如果当前物品可以放入背包,选择放或不放
                dp[i][w] = max(dp[i - 1][w], dp[i - 1][w - weights[i - 1]] + values[i - 1])
            else:
                # 当前物品无法放入背包,选择不放
                dp[i][w] = dp[i - 1][w]
    
    # 返回最大价值
    return dp[n][W]

# 示例
weights = [2, 3, 4, 5]  # 物品重量
values = [3, 4, 5, 6]   # 物品价值
W = 5                   # 背包最大容量

result = knapsack_01(weights, values, W)
print(f"最大价值: {result}")
  • 0-1背包问题 的状态转移依赖于 上一层 的选择,因此需要用二维数组来记录每个物品和每个容量的状态。
  • 完全背包问题 中,每个物品可以选择多次,所以我们可以通过一个一维数组来记录当前背包容量下的最大价值。

标签:背包,capacity,迭代,递归,weights,回溯,物品,values,dp
From: https://blog.csdn.net/2203_75379880/article/details/144176728

相关文章

  • 递归 算法
    递归、搜索与回溯算法1.汉诺塔2.合并两个有序链表3.反转链表4.两两交换链表中的节点5.Pow(x,n)-快速幂1.汉诺塔题目链接:面试题08.06.汉诺塔问题解题思路:首先观察有一个、两个、三个盘子时的情况,手动去挪不难发现,大致都是先将上面n-1个盘子借助C的辅助,挪动到......
  • 回溯算法 part04
    文章参考来源代码随想录491.递增子序列在90.子集II (opensnewwindow)中我们是通过排序,再加一个标记数组来达到去重的目的。而本题求自增子序列,是不能对原数组进行排序的,排完序的数组都是自增子序列了。所以不能使用之前的去重逻辑!1.递归函数参数输入的数组,当前层开始递......
  • 前端番外小知识——可迭代对象
    一,问题如何让下面代码成立var[a,b]={a:1,b:2}console.log(a);console.log(b);二,分析什么是可迭代对象?满足可迭代协议的对象含义:1.具有Symbol.iterator属性2.Symbol.iterator是一个函数3.执行函数返回一个迭代器迭代器1.具有next方法2.执行ne......
  • 递归详细含图解析
    1递归定义:自己调用自己2递归分类:·-直接递归:方法自身调用自己。·-间接递归:A方法调用B方法,B方法调用C方法,C方法再调用A方法。3注意事项·递归一定要有条件限定,保证递归能够停止下来,否则会形成死循环并发生栈内存溢出(StackOverflowError)。·禁止构造方法递归。......
  • 回溯算法简介
    基本思想递归:使用递归的方式实现选择:从根节点开始,逐层搜索树的节点,沿着某一路径深入搜索探索:在搜索的过程中,当遇到一个节点,需要判断是否需要继续搜索该节点的子节点回溯:当探索到某条路径的末尾(树的叶子节点)时或者不满足要求时需要回退到上一个节点特点系统性:对问题的搜索......
  • 25分支限界算法和回溯算法
    回溯算法实际问题:其中回溯算法也可以用于解决n皇后问题#include<iostream>#include<vector>usingnamespacestd;constintN=8;vector<int>col(N,0),diag1(2*N,0),diag2(2*N,0);//标记列和对角线是否有皇后vector<vector<string>>solutions;vector......
  • 递归总结
    比赛后的这几周时间里我们学习了dfs递归,我感觉收货颇丰。递归这个东西呢,你说他简单,他也不简单,说他难吧,他也不难,这里我就拿一些难的题来举例,比如说dance这道题,我感觉相对来说还是比较恶心人的,这种题的难点就在于你枚举什么,整个递归的难点也就在这,但当你知道这种题的枚举方法,这些题......
  • python学习笔记(12)算法(5)迭代与递归
    一、迭代迭代(iteration)是一种重复执行某个任务的控制结构。在迭代中,程序会在满足一定的条件下重复执行某段代码,直到这个条件不再满足。迭代通常用于解决需要逐步推进的计算问题,例如遍历数组、计算阶乘等。迭代的优点是内存使用效率高,易于优化,适合处理大规模数据。1.for循环......
  • # 26_Python基础到实战一飞冲天(二)-python基础(二十六)--缺省多值参数和递归
    26_Python基础到实战一飞冲天(二)-python基础(二十六)–缺省多值参数和递归一、缺省参数-02-指定函数缺省参数的默认值1、指定函数的缺省参数在参数后使用赋值语句,可以指定参数的缺省值。2、指定函数的缺省参数定义示例代码(dzs_14_函数的缺省参数定义.py)#dzs_14_函数的......
  • 非递归线段树实现
    ZKW非递归线段树参考文章:线段树详解(非递归版)_非递归线段树-CSDN博客建树:原数组[1,n]存在线段树的[2,n+1](为了方便区间查询,要空出第一个节点和最后一个节点)区间查询若查询[L,R]区间,选取L-1和R+1两个节点,向上寻找.每次到达父节点L-1查看自己的父亲的右节点......