PHP 程序员为何要学算法?深挖算法的重要性,从背包算法说起

日期: 2024-08-08 19:07:32|浏览: 535|编号: 60113

友情提醒:信息内容由网友发布,本站并不对内容真实性负责,请自鉴内容真实性。

其实,PHP程序员到底要学算法,还是要深挖算法,目前还没有定论。博主即将大四,在找实习的过程中,逐渐发现了学习算法的重要性。博主在学校时的工作室老板曾说过,熟悉算法可以让你的天花板更高,所以才有了这一系列博客,每天一个算法,由简入难,逐步提升你的编程能力。

今天博主想讲一下背包算法。

先来一个问题。场景如下:

0-1背包问题:

有n个物品,1个背包。每个物品i的重量为wi,价值为vi,背包容量为W。每个物品只有一件,可以装也可以不装,不能拆分。如何选择物品装入背包,使得背包中物品总价值最大化?要求算法输出最优值和最优解。

1)问题分析

在选择放入背包的物品时,物品i只有两个选项,放入背包或者不放入背包。物品i不能多次放入背包,也不能只将物品i的一部分放入背包。设xi表示物品i放入背包的情况,当xi=0时,表示不放入​​背包;当xi=1时,表示放入背包。

2)算法思想与算法设计

算法思想:

根据问题分析,设计如下约束和目标函数:

因此,问题归结为寻找一个满足约束并最大化目标函数的解向量 X=(x1,x2,x3,…xn)。

由于 0-1 背包问题的解由向量 (x1, x2, x3, ... xn) 描述。该问题可以视为对 n 维 0-1 向量 (x1, x2, x3, ... xn) 的决策。对于任何分量 xi 的决策都是“决定 xi = 1 或 xi = 0”,i = 1, 2, 3 ..., n。在对 xi-1 做出决策后,序列 (x1, x2, x3, ... xn) 已经确定。在决定 xi 时,问题处于以下两种状态之一:

(1)若背包容量不足以容纳物品i,则xi = 0,放入背包的价值不会增加。

(2)如果背包的容量足以容纳物品i,则xi = 1,背包中物品的价值增加vi

在两种情况下,价值最大的背包的价值应该是对 xi 进行决策后的价值

令 C[i][j] 表示子问题

的最优值

那么,C[i-1][j-wixi]就代表了该问题的一个子问题。

的最优值。

经过分析,最优值的递归定义是:

算法设计:

1:用数组w[n]存储n个物品的重量;数组v[n]存储n个物品的价值,背包容量为W,数组C[n+1][w+1]存储每次迭代的执行结果;数组x[n]用于存储装入背包的物品的状态。

2:初始化。按上述方法递归初始化数组 C

3:循环阶段。根据上面的递归公式,确定前i个物品可以装入背包时的最优值

3-1:当i=1时,求C[1][j],1≤j≤W。

3-2:当i=2时,求C[2][j],1≤j≤W

依此类推,直到...

3-n:当i=n时,求C[n][W],1≤j≤W。此时C[n][W]即为最优值。

4:确定具体要装入背包的物品。从C[n][W]的值开始往前推,若C[n][W]>C[n-1][W],则xn=1,将前n-1个物品装入容量为W-wn的背包中,否则xn=0。以此类推。。。。

得到以下关系:

当 C[i][j] = C[i-1][j] 时 xi=0, j=j

当 C[i][j]>C[i-1][j] 时 Xi=1, j =j-wi

根据公式,你可以确定放入背包的具体物品

3)插图

商品重量:w1 = 7 w2 = 23 w3 = 25 w4 = 24

项目值:v1 = 1 v2 = 8 v3 = 19 v4 = 11

根据算法设计步骤,示意图如下

使用二维数组C[5][53]存储各个子问题的最优值,第i行表示物品,第j列表示背包容量,表格中的数据表示为C[i][j]。

(1)根据公式初始化第0行和第0列,如下图所示

(2)当i=1时,求C[1][j],1≤j≤W。

由于项目1的权重为w1=7,其价值为v1=1,我们可以分为两种情况进行讨论。

1. 若j < wi,即j 2. 若j ≥ w1,即j ≥ 7,则C[1][j]=max{C[0][j],C[0][j-w1]+v1}=max{C[0][j]},C[0][j-7]+1}

i=1时的内容如下

(3)当i=2时,求C[2][j],1≤j≤W。

由于项目2的权重为w2=23,其价值为v2=8,我们可以分为两种情况进行讨论。

1. 若 j < w2,即 j 2. 若 j ≥ w2,即 j ≥ 23,则 C[2][j] = max{C[1][j], C[1][j-w2]+v2} = max{C[1][j]}, C[1][j-23]+8}

i=2时的内容如下

(4)当i=3时,求C[3][j],1≤j≤W。

由于项目3的权重为w3=25,价值为v3=19,因此我们可以分两种情况进行讨论。

1. 若 j < w3,即 j 2. 若 j ≥ w3,即 j ≥ 25,则 C[3][j] = max{C[2][j], C[2][j-w3]+v3} = max{C[2][j]}, C[2][j-25]+19}

i=3时的内容如下

(5)当i=4时,求C[4][j],1≤j≤W。

由于项目4的权重为w4=24,其值为v4=11,因此我们可以分为两种情况进行讨论。

1. 若j < w4,即j 2. 若j ≥ w4,即j ≥ 24,则C[4][j] = max{C[3][j],C[3][j-w4]+v4} = max{C[4][j]},C[4][j-24]+11}

i=4时的内容如下

最后从图5可以看出,背包中装载的物品的最大价值为30

(6)通过将C[n][W]的值向前推进,最终可以找到应该放入背包的具体物品,即问题的最优解。

最初,j=W=52,i=4。

C[4][52]>C[3][52],第4个物品放入背包,x4=1,j=j-24=28。

C[3][28]>C[2][28],第三件物品放入背包,x3=1,j=j-25=3。

C[2][3]=C[1][3],第二件物品未放入背包,x2=0。

C[1][3]=C[0][3],第一个物品未放入背包,x1=0。

该问题的最优解是X=(x1,x2,x3,x4)=(0,0,1,1);

4)算法描述


/*
*背包算法类
*/
class bag {
    private $n;//物品的数量
    private $W;//背包总容量
    private $w = array();//物品的重量数组
    private $v = array();//物品的价值
    public function __construct ($n,$W,$w,$v) {
        //构造函数初始化基本数据
        $this->n = $n;
        $this->W = $W;
        $this->w = $w;
        $this->v = $v;
    }
    //背包算法
    public function knapsack () {
        $n = $this->n;
        $w = $this->w;
        $v = $this->v;
        $W = $this->W;
        $C[$n][$n] = [];
        $x[$n] = [];
        for ($i=0; $i<=$n; $i++) {
            $C[$i][0] = 0; //初始化第0列
        }
        for ($i = 0; $i <= $W; $i++) {
            $C[0][$i] = 0; //初始话第0行
        }
        for ($i = 1;$i <= $n;$i++) { //计算C[$i][$j]
            for ($j=1; $j <= $W; $j++) { 
                if ($j < $w[$i-1]) {
                    $C[$i][$j] = $C[$i-1][$j];
                } else {
                    $C[$i][$j] = max($C[$i-1][$j],$C[$i-1][$j-$w[$i-1]] + $v[$i-1]);
                }
            }
        }
        //构造最优解
        $j = $W;
        for ($i = $n;$i > 0; $i--) {
            if ($C[$i][$j] > $C[$i-1][$j]) {
                $x[$i] = 1;
                $j -= $w[$i-1];
            } else {
                $x[$i] = 0;
            }
        }
        ksort($x);
        return $data = ['maxvalue' => $C[$n][$W], 'maxroad' => $x];//maxvalue为最大价值,maxroad为最优解
    }
}

5)算法分析与验证

a.算法复杂度分析(时间复杂度、空间复杂度)

时间复杂度:在第三个循环中,有两个嵌套的 for 循环。因此,语句 if (j

提醒:请联系我时一定说明是从101箱包皮具网上看到的!