背包通解(详)

本文详细介绍了背包问题的几种类型及其核心算法,包括0-1背包、完全背包、多重背包、分组背包、有依赖的背包问题以及二维费用的背包问题,解析了各种背包问题的初始化状态和递推关系,旨在帮助读者深入理解各类背包问题的解决策略。
摘要由CSDN通过智能技术生成

1、关于0-1背包问题详解:

     对于0-1背包来说,最重要的是分清两点:

     1) 恰好装满:初始化 dp [0] = 0 , dp [1.....n] = -∞

     2)不需要装满:初始化 dp [0....n] = 0 ;

     理解:初始化的dp数组事实上就是在没有任何物 品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量         为0的背包可以在什么也不装且价值为0的情况下被“恰好装满”,其它容量的 背包均没有合法的解,属于未定义的状态,应该         被赋值为-∞了。如果背包并非 必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,这个解的 价值为0,所以初         始时状态的值也就全部为0

     其核心算法为:

     for ( int i = 1 ; i <= n ; i ++)

     for (int j = v ; j >= v[i] ; j--)

    dp [j] = max ( dp [j] , dp [ j - v [i] ] + w [i] );  

2、关于完全背包问题详解:

     其核心算法为:

     for( int i = 1 ; i <= n; i ++)

     for ( int j = v [i] ; j <= v ; j++)

     dp [j] = max ( dp [j] , dp [ j - v [i] ] + w [i] );

3、0-1背包与完全背包的区别:

     在于 j 是从 v ---- v [i] 还是从 v [i] ---- v ;

    其中0-1背包是让v递减,其原理是为了保证第i次循环中的状态dp [j] 是由状态dp [ j - v [i] ] 递 推而来。换句话说,这正是为了        保证每件物品只选一次,保证在考虑“选入 第i件物品”这件策略时,依据的是一个绝无已经选入第 i 件物品的子结果

    dp [ j - v [ i ] ]。

    而现在完全背包的特点恰是每种物品可选无限件,所以在考虑“加 选一件第i种物品”这种策略时,却正需要一个可能已选入第i        种物品的子结 果dp [ j - v [ i ] ],所以就可以并且必须采用v递增的顺序循环。

4、关于多重背包问题详解:

    将多重背包转化为0-1背包:将第i种物品分成若干件01背包中的物品,其中每件物品有一个系 数。这件物品的费用和价值            均是原来的费用和价值乘以这个系数。令这些系数 分别为1,2,22 ...2k−1,Mi −2k + 1,且k是满足Mi −2k + 1 > 0的最大整数。         例 如,如果Mi为13,则相应的k = 3,这种最多取13件的物品应被分成系数分别 为1,2,4,6的四件物品。

    其核心算法为:

    1)for( int i = 1 ; i <= n ; i++)

          for( int  j = 1 ; j < = geshu ; j++)

            for(  int k = v ; k >= jiage ; k--)

              dp [ k ] = max( dp [ k ] , dp [ k - jiage ] + zhongliang);

     2)for( int i = 1 ; i <= n ; i++ ) {

           cin >> v >> w >> c;            

           for( int j = v ; j >= 0 ; j--)

            for( int k =1 ; k <= c && j + k * v <=n ; k++)

            if(dp [ j ] + k * w > dp [ j + k * v ] )

            dp [ j + k * v ] = dp [ j ] + k * w ;

         }

5、分组背包详解:

      其限制条件:要么选一件要么一件都不选

      其核心算法为:

      for( int i = 1; k <= jizu ; i++)

       for( int j = v ; j >= 0 ; j--)

        for( int k = 1 ; k <= j ; k++)

         dp [ j ] = max( dp[ j ] , dp [ j - k ] + a [ i ] [ k ] )

6、有依赖的背包问题(即选A必选B)详解:

      不仅仅只将背包中的最优解输出,要将背包中次优解,次次优解,,,,全部输出

     其核心代码为:

    for( int i = 1 ; i < n ; i++) {
     for( int j = v ; j >= v [ i ] ; j--) {
      for( int t = 1 ; t <= jieshu ; t++)//把所有可能的解都存起来{
       a [ t ] = f [ j ][ t ] ;
       b [ t ] = f [ j - v [ i ] ][ t ] + v [ i ] ;
    }
    int m,x,y;
    m = x = y = 1 ;
    a [ k + 1 ] = b [ jieshu + 1 ] = -1 ;
    //下面的循环相当于求a和b并集,也就是所有的可能解 
    while ( m <= jieshu && (a [ x ] != -1 || b [ y ] != -1) ) {
        if ( a [ x ] > b [ y ] )
            f [ j ][ m ] = a [ x++] ;
        else 
            f [ j ][ m ] = b [ y++] ;    
        if ( f [ j ][ m ] != f [ j ][ m - 1 ] )
            m++;
    }
}

7、二维费用的背包问题详解:

     题意一般为:对于每件物品,具有两种不同的空间耗费,选 择这件物品必须同时付出这两种代价。对于每种代价都有一个可       付出的最大值 (背包容量)。问怎样选择物品可以得到最大的价值。 设这两种代价分别为代价一和代价二,第i件物品所需的       两种代价分别 为Ci和Di。两种代价可付出的最大值(两种背包容量)分别为V 和U。物品的 价值为Wi。
     则其核心算法为: dp [i,v,u] = max{ dp[i−1,v,u] , dp [i−1,v−Ci,u−Di] + Wi} (其与前面的一维背包算法是一样的原理)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值