首页 > 其他分享 >动态规划(五)背包问题

动态规划(五)背包问题

时间:2023-06-01 17:32:43浏览次数:22  
标签:ii 背包 求解 int 问题 最优 动态 规划


基本思想:
动态规划算法通常用于求解具有某种最优性质的问题。在这类问题中,可能会有许多可行解。每一个解都对应于一个值,我们希望找到具有最优值的解。动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的(即下一个子阶段的求解是建立在上一个子阶段的解的基础上,进行进一步的求解)。若用分治法来解这类问题,则分解得到的子问题数目太多,有些子问题被重复计算了很多次。如果我们能够保存已解决的子问题的答案,而在需要时再找出已求得的答案,这样就可以避免大量的重复计算,节省时间。我们可以用一个表来记录所有已解的子问题的答案。不管该子问题以后是否被用到,只要它被计算过,就将其结果填入表中。这就是动态规划法的基本思路。具体的动态规划算法多种多样,但它们具有相同的填表格式。

应用场景:
  动态规划求解具有以下的性质:
  最优子结构性质、子问题重叠性质  
  最优子结构性质:最优解包含了其子问题的最优解,不是合并所有子问题的解,而是找最优的一条解线路,选择部分子最优解来达到最终的最优解。
  子问题重叠性质:先计算子问题的解,再由子问题的解去构造问题的解(由于子问题存在重叠,把子问题解记录下来为下一步使用,这样就直接可以从备忘录中读取)。其中备忘录中先记录初始状态。

2、求解思路

  ①、将原问题分解为子问题(子问题和原问题形式相同,且子问题解求出就会被保存);
  ②、确定状态:01背包中一个状态就是NN个物体中第ii个是否放入体积为VV背包中;
  ③、确定一些初始状态(边界状态)的值;
  ④、确定状态转移方程,如何从一个或多个已知状态求出另一个未知状态的值。(递推型)

动态规划(五)背包问题_01背包

01背包问题求解思路

  ①、确认子问题和状态
  01背包问题需要求解的就是,为了体积V的背包中物体总价值最大化,NN件物品中第ii件应该放入背包中吗?(其中每个物品最多只能放一件)
  为此,我们定义一个二维数组,其中每个元素代表一个状态,即前ii个物体中若干个放入体积为VV背包中最大价值。数组为:f[N][V]f[N][V],其中fijfij表示前ii件中若干个物品放入体积为jj的背包中的最大价值。
  ②、初始状态
  初始状态为f[0][0−V]f[0][0−V]和f[0−N][0]f[0−N][0]都为0,前者表示前0个物品(也就是空物品)无论装入多大的包中总价值都为0,后者表示体积为0的背包啥价值的物品都装不进去。
  ③、转移函数

if (背包体积j小于物品i的体积)
    f[i][j] = f[i-1][j] //背包装不下第i个物体,目前只能靠前i-1个物体装包
else
    f[i][j] = max(f[i-1][j], f[i-1][j-Vi] + Wi)

  最后一句的意思就是根据“为了体积V的背包中物体总价值最大化,NN件物品中第ii件应该放入背包中吗?”转化而来的。ViVi表示第ii件物体的体积,WiWi表示第ii件物品的价值。这样f[i-1][j]代表的就是不将这件物品放入背包,而f[i-1][j-Vi] + Wi则是代表将第i件放入背包之后的总价值,比较两者的价值,得出最大的价值存入现在的背包之中。

#include<iostream>
using namespace std;

int main()
{
    int nArr[6][13] = {{0}};
    int nCost[6] = {0 , 2 , 5 , 3 , 10 , 4};  //花费
    int nVol[6]   = {0 , 1 , 3 , 2 , 6 , 2}; //物体体积
    int bagV = 12;

    for( int i = 1; i< sizeof(nCost)/sizeof(int); i++)
    {
        for( int j = 1; j<=bagV; j++)
        {
            if(j<nVol[i])
                nArr[i][j] = nArr[i-1][j];
            else
                nArr[i][j] = max(nArr[i-1][j] , nArr[i-1][j-nVol[i]] + nCost[i]);       
            cout<<nArr[i][j]<<' ';
        }   
        cout<<endl;
    }
    cout<<nArr[5][12]<<endl;

    return 0;
}

01背包问题其实就可以化简为涂写下面的表格,其中每个数对应数组nArr中每个元素,初始化部分为0,然后从左上角按行求解,一直求解到右下角获取最终解nArr[5][12]。

动态规划(五)背包问题_最优解_02

标签:ii,背包,求解,int,问题,最优,动态,规划
From: https://blog.51cto.com/u_16147764/6396715

相关文章

  • 动态规划(一)硬币找零,机器人路径
    动态规划(DynamicProgramming,简称DP),虽然抽象后进行求解的思路并不复杂,但具体的形式千差万别,找出问题的子结构以及通过子结构重新构造最优解的过程很难统一,并不像回溯法具有解决绝大多数问题的银弹。动态规划求解的一般思路1.硬币找零扩展1:单路取苹果扩展2:机器人路径2.字符......
  • 代理模式(动态)
    1,动态代理分为2类①基于JDK(1.5以后的版本)接口类:点击查看代码publicinterfaceIDAO{publicintsave();publicintremove();publicintmodify();publicintfindAll();}实现类点击查看代码publicclassDeptDAOimplementsIDAO{@Over......
  • 关于动态维护树中点集直径的研究
    例题:P2056.这是括号序动态维护的方法,这里不讲。注意到一个结论:设\(S,T(S\capT=\varnothing)\)为两个树种的点集。记\(f(S)\)为一个大小为\(2\)集合,其中两个点分别为\(S\)集合中直径的两个端点(多个取任意)。则有结论:\(\exists\x,y\inf(S)\cupf(T),x\neqy\),满足\(x......
  • Spring boot 使用 jpa 动态插入@DynamicInsert和动态更新@DynamicUpdate(动态指部分或
    @DynamicInsert属性:设置为true,设置为true,表示insert对象的时候,生成动态的insert语句,如果这个字段的值是null就不会加入到insert语句当中.默认false。比如希望数据库插入日期或时间戳字段时,在对象字段为空的情况下,表字段能自动填写当前的sysdate。@DynamicUpdate属性:设置为tru......
  • 动态库版本控制
    Linux中有一套规则来命名系统中的每一个共享库,它规定共享库的命名规则必须如下libname.so.x.y.z最前面使用前缀“lib”、中间是库的名字和后缀“.so”,最后面跟着的是三个数字组成的版本号。“x”表示主版本号,“y”表示次版本号,“z”表示发布版本号。   发布版本号表示......
  • 01背包问题
    问题描述: 给定n种物品和一背包的容量m,物品i的重量是c[i],其价值是w[i],问如何选择装入背包中的物品总价值最大?每种物品一件,可以选择放或不放。  分析:dp[i][v]表示前i件物品恰放入一个容量为v的背包可以获得的最大价值。则其状态转移方程便是:  这个方程非常重要,基本上所有跟背包......
  • 进阶指南 - 动态规划
    可以说是典中典题了。有很多输出方案的方法。线性DP“线性DP”不是指线性复杂度,而是指动态规划的每个维度的转移都是线性的。解决这类问题的关键是要确定,在当前维度下,每个状态的求解只与之前的最优解有关。MrYoung'sPicturePermutationsSPOJGNYR04HonLuogu给定一个......
  • 图片动态制作,图片动态制作软件分享!​
    图片动态制作是指使用计算机软件和技术将静态图片转化为动态效果的过程。通过添加动画和特效,可以让图片变得更加生动、有趣、吸引人,并增强视觉效果。这种技术被广泛应用于电影、电视、广告、游戏、网站设计等领域,可以为观众提供更加丰富的视觉体验,那么很多小伙伴不知道使用什么软件......
  • 1.动态数组
    1.动态数组结构  上图所示,该动态数组有3个元素,空间容量是6,每个元素类型为void*,因为void*可以接受任何类型指针,可以用来存各种类型指针。第一个元素地址为pAddr,第一个元素为*pAddr。用结构体表示动态数组为://动态数组结构体structdynamicArray{ void**pAddr;//维护真实......
  • C/C++杂记:运行时类型识别(RTTI)与动态类型转换原理
    运行时类型识别(RTTI)的引入有三个作用:配合typeid操作符的实现;实现异常处理中catch的匹配过程;实现动态类型转换dynamic_cast。1.typeid操作符的实现1.1.静态类型的情形C++中支持使用typeid关键字获取对象类型信息,它的返回值类型是conststd::type_info&,例:#include<type......