• 算法设计与分析-0/1背包问题


    0/1背包问题

    1.分析最优解的结构

    ​ 0/1背包问题可以形式化表述为一个整数规划问题:
    m a x ∑ i = 1 n v i x i       { ∑ i = 1 n w i x i ≤ c x i ∈ { 0 , 1 } 1 ≤ i ≤ n max\sum_{i=1}^n{v_ix_i} \ \ \ \ \ {ni=1wixicxi{0,1}1in

    {ni=1wixicxi{0,1}1in
    maxi=1nvixi     {i=1nwixicxi{0,1}1in
    ​ 问题的解为一个n元0-1向量, ( x 1 , x 2 , x 3 , . . . , x n ) ,   x i ∈ { 0 , 1 }   ( 1 ≤ i ≤ n ) (x_1,x_2,x_3,...,x_n),\ x_i \in \{0,1\} \ (1 \leq i \leq n) (x1,x2,x3,...,xn), xi{0,1} (1in)。0/1背包问题具有最优子结构性质,因此可以使用动态规划方法解决。最优子结构性质证明如下:

    ​ 首先假设原问题的一个最优解为 ( x 1 , x 2 , x 3 , . . . , x n ) (x_1,x_2,x_3,...,x_n) (x1,x2,x3,...,xn),考虑0/1背包的一个子问题为:
    m a x ∑ i = 1 n − 1 v i x i       { ∑ i = 1 n − 1 w i x i ≤ c − w n x n x i ∈ { 0 , 1 } 1 ≤ i ≤ n − 1 max\sum_{i=1}^{n-1}{v_ix_i} \ \ \ \ \ {n1i=1wixicwnxnxi{0,1}1in1

    {n1i=1wixicwnxnxi{0,1}1in1
    maxi=1n1vixi     {i=1n1wixicwnxnxi{0,1}1in1
    ​ 则相应的子问题的最优解应该为 ( x 1 , x 2 , x 3 , . . . , x n − 1 ) (x_1,x_2,x_3,...,x_{n-1}) (x1,x2,x3,...,xn1)。假设存在一个解 ( x 1 ′ , x 2 ′ , x 3 ′ , . . . , x n − 1 ′ ) (x'_1,x'_2,x'_3,...,x'_{n-1}) (x1,x2,x3,...,xn1),使 ∑ i = 1 n − 1 v i x i ′ > ∑ i = 1 n − 1 v i x i \sum_{i=1}^{n-1}{v_ix'_i}>\sum_{i=1}^{n-1}{v_ix_i} i=1n1vixi>i=1n1vixi,由于 ∑ i = 1 n − 1 w i x i ≤ c − w n x n \sum_{i=1}^{n-1}{w_ix_i}\leq c-w_nx_n i=1n1wixicwnxn,可得 ∑ i = 1 n − 1 w i x i + w n x n ≤ c \sum_{i=1}^{n-1}{w_ix_i}+w_nx_n\leq c i=1n1wixi+wnxnc,即存在一个n元0-1向量 ( x 1 ′ , x 2 ′ , x 3 ′ , . . . , x n − 1 ′ , x n ) (x'_1,x'_2,x'_3,...,x'_{n-1},x_n) (x1,x2,x3,...,xn1,xn)是原问题的一个可行解。可以得到:
    ∑ i = 1 n − 1 v i x i ′ + v i x n > ∑ i = 1 n − 1 v i x i + v i x n = ∑ i = 1 n v i x i \sum_{i=1}^{n-1}{v_ix'_i}+v_ix_n>\sum_{i=1}^{n-1}{v_ix_i}+v_ix_n=\sum_{i=1}^n{v_ix_i} i=1n1vixi+vixn>i=1n1vixi+vixn=i=1nvixi
    ​ 即这个可行解计算的结果比原问题的最优解要大,这产生了矛盾。因此可以证明0/1背包问题具有最优子结构性质。

    2.建立递归关系

    ​ 设0/1背包问题的子问题为:
    m a x ∑ k = 1 i v k x k       { ∑ k = 1 i w k x k ≤ j x k ∈ { 0 , 1 } 1 ≤ k ≤ i max\sum_{k=1}^i{v_kx_k} \ \ \ \ \ {ik=1wkxkjxk{0,1}1ki

    {ik=1wkxkjxk{0,1}1ki
    maxk=1ivkxk     {k=1iwkxkjxk{0,1}1ki
    ​ 最优解用m(i,j)表示,i表示可选物品1-i,j表示容量为j。根据0/1背包的最优子结构性质,可以得到计算m(i,j)的递归式如下:
    i = 1      m ( i , j ) = { 0 0 ≤ j < w i v i w i ≤ j i > 1      m ( i , j ) = { m ( i − 1 , j ) 0 ≤ j < w i m a x { m ( i − 1 , j ) ,   m ( i − 1 , j − w i ) + v i } w i ≤ j i = 1 \ \ \ \ m(i,j)= {00j<wiviwij
    {0vi0j<wiwij
    \\ i>1 \ \ \ \ m(i,j)= {m(i1,j)0j<wimax{m(i1,j), m(i1,jwi)+vi}wij
    i=1    m(i,j)={0vi0j<wiwiji>1    m(i,j)={m(i1,j)max{m(i1,j), m(i1,jwi)+vi}0j<wiwij

    3.计算最优值

    ​ 根据以上构造的递推关系,进行最优值的计算。

    int solution(int m[][c+1],int weight[],int value[],int c,int n){			
        //初始化,当j>=weight[0],m[0][j]=value[0]
        memset(dp,0,sizeof(dp));
        for(int j=weight[0];j<=c;j++) m[0][j]=value[0];
        for(int i=1;i
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    ​ 主要的计算量为m[i][j]的计算,因此该算法的时间复杂度为 O ( c n ) O(cn) O(cn)

    4.构造最优解

    ​ 根据m[i][j]中记录的信息判断最优解是从哪个子问题产生的,得到结果的0-1向量:

    void traceback(int m[][c+1], int weight[] ,int n, int c, int x[]){
        for(int i=1;i
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    Spring Security进行权限控制
    Jetson TX2 NX安装遇到的问题汇总
    硫酸软骨素-聚乙二醇-卵清蛋白,Chondroitin sulfate-PEG-OVA/Ovalbumin
    【Visual Leak Detector】在 VS 高版本中使用 VLD
    【Linux 操作系统】I /O输入与输出
    1、广告-互联网展示广告发展史
    AES-GCM算法 Java与Python互相加解密
    FITC-PEG-FA,Folic acid-PEG-Fluorescein,叶酸PEG荧光素
    【深度学习框架格式转化】【GPU】Pytorch模型转ONNX模型格式流程详解【入门】
    【MySQL进阶】SQL性能分析
  • 原文地址:https://blog.csdn.net/Aaron503/article/details/127705844