zoukankan      html  css  js  c++  java
  • 01背包

    什么是背包问题

      背包问题(Knapsack problem)可以描述为:给定一组物品,每种物品都有自己的价格和价值,在限定的总价格内,我们如何选择,才能使得物品的总价值最高。

    什么是01背包

      01背包指的就是每件物品要么选,要么不选。如果选,只能选一件

    如何求解01背包

             先来分析一下01背包的特征。结果我们发现01背包具有最优子结构(自己去查这是什么意思)。有最有子结构的问题自然要用动态规划来解。

             说道动态规划,就一定要有动态转移方程。

    第一件事就是确定转移方程的维度。容易看出,转移方程有两个维度,分别是价值价格

    接下来就是确定转移方程。我们先考虑在空间为m,有n-1件物品时的最优解,然后判断选或不选第n件物品的价值,取最大值作为f(n, m)的值。可得转移式为

    f(n,m)=max⁡{ f(n-1,m),f(n-1,m-w[n])+v[n] }

      其实这个时候就可以求解01背包了。但是二维的转移矩阵往往出现爆空间的情况。于是就要进行优化。

    优化动态转移矩阵

             由上表和转移矩阵可以得出当前节点只会依赖到上面一行的数据,这样就可以吧二维数组压缩到两个一维数组。像放鞭炮一样往下放。

     

      这样其实已经很好了,空间被优化成线性。但是这样做有一个缺点,就是两个数组来回倒会大大增加代码的长度和调试时间。那把数组直接优化成一维不就好了吗?可以的。因为我们发现,当前格子只可能依赖到自己上面和左边的格子,不可能依赖到自己右面的格子。

    那么就可以把数组压缩成一维的。但是计算要逆序,不然就会覆盖掉上次的计算结果,导致计算出错。

    此时,转移方程就变成了

    f(m)=max⁡{ f(m),f(m-w[n])+v[n] }

    再次强调,v要逆序!像这样:

    1.    memset(f,0,sizeof f);  
    2.    for (int n = 0; n < N; ++n) {  
    3.        for (int m = M; M >= 0; ++m) {  
    4.            f[m] = max(f[m], f[m - w[n]] + v[n])  
    5.        }  
    6.    }  
  • 相关阅读:
    看鸟哥的Linux私房菜的一些命令自我总结(三)
    NYOJ8——一种排序
    分布计算系统学习随笔 第四章 命名与保护
    NYOJ7——街区最短路径问题
    分布计算系统学习随笔 第一章绪论
    看妮妮视频留下的一些链接~~
    NYOJ6——喷水装置(一)
    看鸟哥的Linux私房菜的一些命令自我总结(二)
    NYOJ5——Binary String Matching
    高性能Javascript笔记
  • 原文地址:https://www.cnblogs.com/Iuppiter/p/12183181.html
Copyright © 2011-2022 走看看