软考-软件设计师:算法策略:贪心法(一般用于求满意解)

介绍

局部最优,但整体不见得最优。每步有明确的、既定的策略。

审题技巧

没有明确的文字特征,可能有 关注现在 字样,如果做题时,遇到这种情况,一般是贪心法

经典问题

  • 背包问题页(如装箱)
  • 多机调度
  • 找零钱问题
  • 最小生成树问题(普里姆算法、克鲁斯卡尔算法)

案例 - 部分背包问题

如上图:
有一个背包,背包容量是 70
有 3 个物品:

  • 物品1,重量 20,价值 140
  • 物品2,重量 30,价值 180
  • 物品3,重量 40,价值 200

物品可以 分割成任意大小。要求尽可能让装入背包中的物品 总价值最大,但不能超过总容量。

实现方式一(局部最优、整体不是最优):

计算出各个物品的单价,即:单价 = 价格 / 重量,将 单价 最高 的物品装起来,此时 局部最优

  • 物品1,单价 7
  • 物品2,单价 6
  • 物品3,单价 5

物品1、物品2 单价 最高,且总重量不超过背包限制,将其装入到背包,如下图:

缺点:

  • 局部最优:放入的物品都是单价最高的
  • 整体不是最优:如果放入 物品2、物品3,总价值是 380,超过本方法的价值

实现方式二(局部最优、整体不是最优):

将 价值 最高的物品 装起来,此时 局部最优

  • 物品1,重量 20,价值 140
  • 物品2,重量 30,价值 180
  • 物品3,重量 40,价值 200

物品2、物品3 价值最高,且总重量不超过背包限制,将其装入到背包,如下图:

缺点:

  • 局部最优:放入的物品价值最高
  • 整体不是最优:见实现方法三

实现方式三(最优):

计算出各个物品的单价,即:单价 = 价格 / 重量,将 单价 最高 的物品装起来,此时 局部最优

  • 物品1,单价 7
  • 物品2,单价 6
  • 物品3,单价 5

物品1、物品2 单价 最高,且总重量不超过背包限制,将其装入到背包,如下图:

还空出 20 的容量,将 物品3 分割一半,放入进去,如下:

此时才是最优解

案例 - 旅行家问题

有4个点:A起点,B、C、D,各点距离如下:

  • A→B = 1(最近,贪心必选)
  • A→C = 2
  • A→D = 100

  • B→C = 100(巨远)

  • B→D = 100(巨远)
  • C→D = 1(超级近)

旅行家 每个城市只走一次,最后回到起点 A,走的路程最短

用贪心算法是错误的

贪心算法(最近邻)

  1. A 出发,最近是 B(1)
    路径:A→B
  2. 在 B,只能去 C 或 D,都 100,选 C
    路径:A→B→C
  3. 在 C,只剩 D
    路径:A→B→C→D
  4. D 返回 A(100)

总距离 = 1 + 100 + 1 + 100 = 202

时间复杂度

这个贪心算法的核心流程是:

  1. 从中央仓库出发,作为当前地点。
  2. 从所有未访问的运输目的地中,找到离当前地点最近的一个,将其加入路径,并标记为已访问。
  3. 将新加入的地点设为当前地点。
  4. 重复步骤2和3,直到所有运输目的地都被访问过。
  5. 最后从最后一个地点返回中央仓库。

对于 n 个运输目的地,我们需要执行 n 次“选择下一个地点”的操作。

单次选择的时间复杂度

在每一次选择下一个地点时,我们需要:

  • 遍历所有未访问的运输目的地。
  • 计算(或查找)当前地点到每个未访问地点的距离。
  • 找到其中距离最小的那个。

在最坏情况下,第一次选择时有 n 个地点可选,第二次有 n-1 个,第三次有 n-2 个,以此类推。因此,单次选择的时间复杂度是线性的,即 O(k),其中 k 是当前未访问地点的数量。

总时间复杂度计算

n + (n-1) + (n-2) + \ldots + 1 = \frac{n(n+1)}{2} = n^2


真正最优路径(不贪心)

最优走法:
A → C → D → B → A

总距离 = 2 + 1 + 100 + 1 = 104

  • 贪心:202
  • 最优:104

原文出处:/show_1GW2lAoteCya.html