2019-04-05  2024-09-15    896 字  2 分钟

背包的状态转换方程 : $_math_inline$f[i,j] = Max\lbrace f[i-1,j-W_i]+Pi( j >= W_i ), f[i-1,j] \rbrace$math_inline_$

$_math_inline$f[i,j]$math_inline_$ 表示在前i件物品中选择若干件放在承重为 j 的背包中,可以取得的最大价值。 Pi表示第i件物品的价值。 决策:为了背包中物品总价值最大化,第 i件物品应该放入背包中吗 ?

假设山洞里共有a,b,c,d ,e这5件宝物(不是5种宝物),它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包, 怎么装背包,可以才能带走最多的财富。

有编号分别为a,b,c,d,e的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?

name weight value 1 2 3 4 5 6 7 8 9 10
a 2 6 0 6 6 9 9 12 12 15 15 15
b 2 3 0 3 3 6 6 9 9 9 10 11
c 6 5 0 0 0 6 6 6 6 6 10 11
d 5 4 0 0 0 6 6 6 6 6 10 10
e 4 6 0 0 0 6 6 6 6 6 6 6

首先要明确这张表是自底向上从左到右生成的。

只要你能通过找规律手工填写出上面这张表就算理解了01背包的动态规划算法。

为了叙述方便,用e2单元格表示e行2列的单元格,这个单元格的意义是用来表示只有物品e时,有个承重为2的背包,那么这个背包的最大价值是0,因为e物品的重量是4,背包装不了。

对于d2单元格,表示只有物品e,d时,承重为2的背包,所能装入的最大价值,仍然是0,因为物品e,d都不是这个背包能装的。

同理,c2=0,b2=3,a2=6。

对于承重为8的背包,a8=15,是怎么得出的呢?

根据01背包的状态转换方程,需要考察两个值,

一个是 $_math_inline$f[i-1,j]$math_inline_$ ,对于这个例子来说就是b8的值9,另一个是 $_math_inline$f[i-1,j-Wi]+Pi$math_inline_$ ;

在这里,

$_math_inline$f[i-1,j]$math_inline_$ 表示我有一个承重为8的背包,当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值

$_math_inline$f[i-1,j-Wi]$math_inline_$ 表示我有一个承重为6的背包(等于当前背包承重减去物品a的重量),当只有物品b,c,d,e四件可选时,这个背包能装入的最大价值

$_math_inline$f[i-1,j-Wi]$math_inline_$ 就是指单元格b6,值为9,Pi指的是a物品的价值,即6

 1void FindMax(){
 2    memset(V, 0, sizeof(V));
 3    for(int i = 1; i <= number; ++i){
 4        for(int j = 1; j <= capacity; ++j){
 5            if(j<w[i]){ // 装不进去
 6                V[i][j] = V[i-1][j];
 7            }else{ // 能装
 8                if(V[i-1][j] > V[i-1][j-w[i]]+v[i]){ // 不装价值大
 9                	V[i][j] = V[i-1][j];
10                }else{ // 前i-1个物品的最优解与第i个物品的价值之和更大
11                    V[i][j] = V[i-1][j-w[i]]+v[i];
12                }
13            }
14        }
15    }
16}

除另有声明外本博客文章均采用 知识共享 (Creative Commons) 署名 4.0 国际许可协议 进行许可转载请注明原作者与文章出处