动态规划之01背包详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态规划之01背包详解相关的知识,希望对你有一定的参考价值。

先看问题:

有N件物品和一个容量为V的背包。(每种物品均只有一件)第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。

通过阅读问题,因为背包就是要往里面放东西,所以一件物品就是有放或不放两种情况,那么怎么才能判断当前物品该不该放进去从而使利益最大化呢。

首先,我们用i代表前i件物品,v代表包的最大承重,ci是第i件物品的重量、wi是第i件物品的价值、f[i,j]是最大价值(i个物品放入有j个空间的包)。

第一种情况:第i件不放进去,这时所得价值(f[i][j])为:f[i][j]=f[i-1][v]

因为不放进去,所以说当前价值(f[i][j])为前i-1个物品的价值f[i-1][v]:当前i个物品用j个空间所拥有的价值就等于前i-1个物品用j个空间的价值,因为物品i没有放进去,

所以就相当于继承f[i-1][v]了,所以f[i][j]=f[i-1][v]

另一种情况:第i件放进去,这时所得价值为:f[i][j]=f[i-1][v-c[i]]+w[i]

因为放进去了,所以说当前价值(f[i][j])不是前i-1个物品的价值f[i-1][v]:因为你放进去了,所以这个时候包内的空间就不是v了,而应该是v-c[i],所以说,

你现在需要继承前i-1个物品占用体积为v-c[i]时的价值,因为你将物品放进去了,所以还需要加上当前物品价值wi,所以f[i][j]=f[i-1][v-c[i]]+w[i]

因为对于第i件物品就是这两种操作,而你又想要最大价值,所以

f[i][j]=max(f[i-1][v],f[i-1][v-c[i]]+w[i])

贴一段代码:(n为物品数量)

for (int i=1;i<=n;++i)
{ for (int j=v;j>=1;--j)
   { if(c[i]<=j)//如果当前物品可以放入当前空间的背包 f[i][j]=max(f[i-1][j],f[i-1][j-c[i]]+w[i]); else f[i][j]=f[i-1][j];//如果当前物品放不进去,那么继承前i个物品在当前空间大小时的价值    } }

当n=3,v=6时的表格:

c[1]=2 , w[1]=7 ;  c[2]=3 , w[2]=1 ; c[3]=5 , w[3]=4;我用红色的数字标记一下在当前代码下填表的顺序,运行之后f[n][v]为最优值,可见此时最优值为f[3][6]=8;

 

i\j

j=0 j=1 j=2 j=3 j=4 j=5 j=6

i=0

0 0 0 0 0 0 0

i=1

0 (6)7 (5)7 (4)7 (3)7 (2)7 (1)7

i=2

0 (12)8 (11)8 (10)8 (9)8 (8)8 (7)8

i=3

0 (18)0 (17)0 (16)0 (15)0 (14)8 (13)8

 

以上是用二维数组存储的,其实还可以用一维数组存储进行空间优化(滚动数组)

从上面计算f[i][j]可以看出,在计算f[i][j]时只使用了f[i-1][0……j],所以说并没有使用其他子问题,所以说在存储子问题解的时候,只用存储f[i-1]的子问题解即可;所以说可以用一个一维数组替换掉那个二维数组,一个存储子问题,一个存储正在解决的子问题。

我们用f[v]表示当前状态是容量为v的背包所得价值

那滚动数组应当如何滚动呢,用二维数组计算f[i][j]时只使用了f[i-1][0……j],而并没有使用到f[i-1][j+1],所以在计算j的循环的时候,让j=M……1

这个时候你也许会问,那你上面用的二维数组不也是逆序吗,其实对于二维数组的来说,正逆序无所谓,当你懂得01背包的算法之后就可以明白这一点

下面给出一维数组优化过的代码:

for (int i=1;i<=n;++i)
{
        for (int j=v;j>=0;--j)
    {
            if(t[i]<=j)
            f[j]=max(f[j],f[j-t[i]]+t[i]);
            else f[j]=f[j];
     }
}

  因为二维的我已经讲解的很详细了,所以一维数组的跟二维数组的相差的不是太多,只要你懂了二维数组的那个是如何工作的,这个我相信你也会很容易理解,我这里就不细化讲解了。

本文章原创,未经我允许不得转载

Authentic Author : Tranx

2017.10.1  21:11













以上是关于动态规划之01背包详解的主要内容,如果未能解决你的问题,请参考以下文章

动态规划之01背包详解

背包之01背包完全背包多重背包详解

动态规划1 —— 01背包详解

动态规划1 —— 01背包详解

超棒的DP问题详解之初识动态规划

动态规划之01背包问题(含代码C)