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} (其与前面的一维背包算法是一样的原理)