算法设计与分析-习题9.1

目录

[1.为找零问题写一个贪婪算法的伪代码,它以金额n和硬币的面额。 ​编辑 作为输入。该算法的时间效率类型是怎样的?](#1.为找零问题写一个贪婪算法的伪代码,它以金额n和硬币的面额。 编辑 作为输入。该算法的时间效率类型是怎样的?)

[2.设计一个处理分配问题的贪婪算法(参见 3.4节)。这个贪婪算法总是能产生最优解吗?](#2.设计一个处理分配问题的贪婪算法(参见 3.4节)。这个贪婪算法总是能产生最优解吗?)

[3.作业调度 如果在单处理器上,有n个运行时间分别为t₁,t₂,...,tₙ的已知作业,请考虑它们的调度问题。这些作业可以按任意顺序执行,一次只能执行一个作业。要求是安排一个调度计划,使得所有的作业在系统中花费的时间最少(一个作业在系统中花费的时间是该作业用于等待的时间和用于运行的时间的总和)。为该问题设计一个贪婪算法。这个贪婪算法总是能产生最优解吗?](#3.作业调度 如果在单处理器上,有n个运行时间分别为t₁,t₂,…,tₙ的已知作业,请考虑它们的调度问题。这些作业可以按任意顺序执行,一次只能执行一个作业。要求是安排一个调度计划,使得所有的作业在系统中花费的时间最少(一个作业在系统中花费的时间是该作业用于等待的时间和用于运行的时间的总和)。为该问题设计一个贪婪算法。这个贪婪算法总是能产生最优解吗?)

[4. 相容区间 给定实数轴上n个开区间(a₁,b₁),(a₂,b₂), ...,(an,bₙ),每个区间表示占用相同资源的任务的开始时间和结束时间,问题是找最大的相容区间数,使得这些区间互不重叠。基于下列策略,研究三个贪婪算法:](#4. 相容区间 给定实数轴上n个开区间(a₁,b₁),(a₂,b₂), …,(an,bₙ),每个区间表示占用相同资源的任务的开始时间和结束时间,问题是找最大的相容区间数,使得这些区间互不重叠。基于下列策略,研究三个贪婪算法:)

a.最早开始时间优先

反例:

b.最短占用时间优先

反例:

c.最早完成时间优先

[5.重温过桥问题 考虑一下广义的过桥问题(习题 1.2的第 2 题)。有n>1个人,他们的过桥时间分别是t₁,t₂,...,tn。问题的其他条件不变:同一时间只能有两个人一起过桥(他们的速度等于较慢者的速度),他们身边带着这群人仅有的一支手电筒。为该问题设计一个贪婪算法,求出用该算法过桥需要多少时间。对于该问题的任何实例,该算法都能生成最小过桥时间吗?如果能,请证明:如果不能,请给出人数最少的实例。](#5.重温过桥问题 考虑一下广义的过桥问题(习题 1.2的第 2 题)。有n>1个人,他们的过桥时间分别是t₁,t₂,…,tn。问题的其他条件不变:同一时间只能有两个人一起过桥(他们的速度等于较慢者的速度),他们身边带着这群人仅有的一支手电筒。为该问题设计一个贪婪算法,求出用该算法过桥需要多少时间。对于该问题的任何实例,该算法都能生成最小过桥时间吗?如果能,请证明:如果不能,请给出人数最少的实例。)

[6. 向下均分 有n>1个相同的缸,其中一个有W品脱的水,而别的缸为空。你被允许执行下列操作:取两个缸,然后把他们中的水在两个缸之间均分。目标是通过执行上述一系列操作,使得初始有水的缸中的水最小化。完成这个任务的最好方法是什么?](#6. 向下均分 有n>1个相同的缸,其中一个有W品脱的水,而别的缸为空。你被允许执行下列操作:取两个缸,然后把他们中的水在两个缸之间均分。目标是通过执行上述一系列操作,使得初始有水的缸中的水最小化。完成这个任务的最好方法是什么?)

[7. 谣言传播 有 n个人,每个人都拥有不同的谣言。通过发电子信息,他们想互相共享所有的谣言。假定发送者会在信息中包含他已知的所有谣言,而且一条信息只有一个收信人。设计一个贪心算法,保证在每个人都能获得所有谣言的条件下,使发送的信息数最小。](#7. 谣言传播 有 n个人,每个人都拥有不同的谣言。通过发电子信息,他们想互相共享所有的谣言。假定发送者会在信息中包含他已知的所有谣言,而且一条信息只有一个收信人。设计一个贪心算法,保证在每个人都能获得所有谣言的条件下,使发送的信息数最小。)

[8.巴切特砝码问题 求n个砝码{w₁,w₂,...,wₙ}的一个集合,使得它可以对天平上重量范围从1到W的任意整数负载进行称重。分别对下面两种条件求解:](#8.巴切特砝码问题 求n个砝码{w₁,w₂,…,wₙ}的一个集合,使得它可以对天平上重量范围从1到W的任意整数负载进行称重。分别对下面两种条件求解:)

a.砝码只能放在天平的一边。

b.砝码能够放在天平的两边。

9.

[a.对下面的图应用 Prim 算法。优先队列中包括所有不在树中的顶点。](#a.对下面的图应用 Prim 算法。优先队列中包括所有不在树中的顶点。)

[b.对下面的图应用 Prim 算法。优先队列中只包括边缘顶点(这种顶点不在树中,但它至少和一个树中的顶点相邻)。](#b.对下面的图应用 Prim 算法。优先队列中只包括边缘顶点(这种顶点不在树中,但它至少和一个树中的顶点相邻)。)

[10.最小生成树的概念可以应用于加权连通图。在应用 Prim 算法之前是否需要检查图的连通性,还是该算法本身就能完成这种检查?](#10.最小生成树的概念可以应用于加权连通图。在应用 Prim 算法之前是否需要检查图的连通性,还是该算法本身就能完成这种检查?)

[11.如果图的边权重可为负, Prim 算法总是能正确求出最小生成树吗?](#11.如果图的边权重可为负, Prim 算法总是能正确求出最小生成树吗?)

[12.令T是由 Prim 算法得到的图G的最小生成树。通过对G增加一个新的顶点和一些新的边,假设新边有权重且新边连接新顶点和图G中的某些顶点,从而得到一个新图Gnew。我们能通过仅对T增加一条新边,就能构造出图Gnew的一棵最小生成树吗?如果回答是,请解释如何得到;如果回答否,请解释为什么不能。](#12.令T是由 Prim 算法得到的图G的最小生成树。通过对G增加一个新的顶点和一些新的边,假设新边有权重且新边连接新顶点和图G中的某些顶点,从而得到一个新图Gnew。我们能通过仅对T增加一条新边,就能构造出图Gnew的一棵最小生成树吗?如果回答是,请解释如何得到;如果回答否,请解释为什么不能。)

[13.如果连通图的边不含权,如何应用 Prim 算法得到该图的一棵最小生成树? Prim算法是求解该问题的好算法吗?](#13.如果连通图的边不含权,如何应用 Prim 算法得到该图的一棵最小生成树? Prim算法是求解该问题的好算法吗?)

14.请证明:如果加权连通图的每一个权重都是唯一的,它只具有唯一的最小生成树。

15.设计一个高效的算法来改变最小堆的一个元素值。该算法的时间效率如何?


1.为找零问题写一个贪婪算法的伪代码,它以金额n和硬币的面额。 作为输入。该算法的时间效率类型是怎样的?

贪婪策略:每次尽可能使用面额最大的硬币,直到金额为 0。

复制代码
算法 GREEDY_CHANGE(n, D[1..m])
    // 输入:总金额 n,硬币面额数组 D[1..m],满足 D[1]>D[2]>...>D[m]
    // 输出:每种硬币的使用数量 C[1..m],总硬币数最少
    初始化数组 C[1..m] 为全 0
    remaining = n  // 剩余需要找零的金额
    
    for i = 1 to m:
        while remaining >= D[i]:
            C[i] = C[i] + 1
            remaining = remaining - D[i]
        if remaining == 0:
            break  // 提前结束
    
    return C

效率为Θ(nm)

2.设计一个处理分配问题的贪婪算法(参见 3.4节)。这个贪婪算法总是能产生最优解吗?

逐行版本:从成本矩阵的第一行开始,到最后一行结束,选择该行中不在之前已标记列中的最小元素。选中此类元素后,将其所在列标记,以防从同一列中选择另一元素。整矩阵版本:重复以下操作n次。在成本矩阵中未标记的行和列中选择最小元素,然后标记其所在行和列。但是,分配问题属于加权二分图匹配,贪婪算法只能得到近似解,不能保证全局最优。只有匈牙利算法才能保证最优。比如这个反例:

3.作业调度 如果在单处理器上,有n个运行时间分别为t₁,t₂,...,tₙ的已知作业,请考虑它们的调度问题。这些作业可以按任意顺序执行,一次只能执行一个作业。要求是安排一个调度计划,使得所有的作业在系统中花费的时间最少(一个作业在系统中花费的时间是该作业用于等待的时间和用于运行的时间的总和)。为该问题设计一个贪婪算法。这个贪婪算法总是能产生最优解吗?

策略:每次选择当前剩余作业中运行时间最短的作业先运行,

复制代码
算法 SCHEDULE(t[1..n]):
    // 输入:作业运行时间数组 t
    // 输出:作业执行顺序
    
    将作业按运行时间 t_i 从小到大排序
    按这个顺序依次执行作业
    
    返回该执行顺序

对于 "总完成时间最小" 这个目标,它是严格最优的。

4. 相容区间 给定实数轴上n个开区间(a₁,b₁),(a₂,b₂), ...,(an,bₙ),每个区间表示占用相同资源的任务的开始时间和结束时间,问题是找最大的相容区间数,使得这些区间互不重叠。基于下列策略,研究三个贪婪算法:

a.最早开始时间优先

反例:

  • 1, 100

  • 2, 3

  • 4, 5

  • 算法选:[1,100] → 只能选 1 个

  • 最优:[2,3]、[4,5] → 2 个

b.最短占用时间优先

反例:

  • 0, 4\] 长度 4

  • 5, 9\] 长度 4

  • 最优:[0,4]、[5,9] → 2 个

c.最早完成时间优先

  • 设贪婪解为 G,最优解为 O。
  • 按结束时间排序,逐个比较:贪心选的第 k 个区间的结束时间 ≤ 最优解第 k 个的结束时间。
  • 因此贪心解不会比最优解短
  • 贪心解就是最优解。

对于以上每个算法,要么证明该算法能够给出最优解,要么给出一个反例表明它不能生成最优解。

5.重温过桥问题 考虑一下广义的过桥问题(习题 1.2的第 2 题)。有n>1个人,他们的过桥时间分别是t₁,t₂,...,tn。问题的其他条件不变:同一时间只能有两个人一起过桥(他们的速度等于较慢者的速度),他们身边带着这群人仅有的一支手电筒。为该问题设计一个贪婪算法,求出用该算法过桥需要多少时间。对于该问题的任何实例,该算法都能生成最小过桥时间吗?如果能,请证明:如果不能,请给出人数最少的实例。

每次都让最快的人(t₁)来回送手电筒

  1. t₁ 和 tᵢ 一起过去 → 时间 +ti
  2. t₁ 独自回来 → 时间 +t1
  3. 把剩下的人一个个送过去
  4. 最后 t₁ 和 t₂ 一起过去 → 时间 +t2

但这不是最优方法,反例如下:t1​=1, t2​=2, t3​=5, t4​=8,用贪婪算法是8+1+5+1+2=17

但实际上最快的是让两个最慢的人一起过去,减少慢人重复走

  1. 1+2 → +2
  2. 1 回 → +1
  3. 5+8 → +8
  4. 2 回 → +2
  5. 1+2 → +2

总时间:2+1+8+2+2=15

6. 向下均分 有n>1个相同的缸,其中一个有W品脱的水,而别的缸为空。你被允许执行下列操作:取两个缸,然后把他们中的水在两个缸之间均分。目标是通过执行上述一系列操作,使得初始有水的缸中的水最小化。完成这个任务的最好方法是什么?

每次取一个空缸,然后均分,最多有n-1次这样的操作,这样初始缸中的水量最小为 W/(2^(n-1)),无法再小。

7. 谣言传播 有 n个人,每个人都拥有不同的谣言。通过发电子信息,他们想互相共享所有的谣言。假定发送者会在信息中包含他已知的所有谣言,而且一条信息只有一个收信人。设计一个贪心算法,保证在每个人都能获得所有谣言的条件下,使发送的信息数最小。

8.巴切特砝码问题 求n个砝码{w₁,w₂,...,wₙ}的一个集合,使得它可以对天平上重量范围从1到W的任意整数负载进行称重。分别对下面两种条件求解:

a.砝码只能放在天平的一边。

使用 2 的幂每个砝码选或不选 ,对应二进制,能表示 1~2^(n−1) 所有整数

b.砝码能够放在天平的两边。

使用 3 的幂,每个砝码有三种选择

  • 左边 (称物侧):相当于
  • 右边 (砝码侧):相当于
  • 不放:相当于0

这正好对应三进制表示,能连续称到 (3^n−1)/2​。

9.

a.对下面的图应用 Prim 算法。优先队列中包括所有不在树中的顶点。

表格如下:

b.对下面的图应用 Prim 算法。优先队列中只包括边缘顶点(这种顶点不在树中,但它至少和一个树中的顶点相邻)。

10.最小生成树的概念可以应用于加权连通图。在应用 Prim 算法之前是否需要检查图的连通性,还是该算法本身就能完成这种检查?

  • 用优先队列每次选取距离当前生成树最近的顶点加入树中。
  • 如果图不连通 ,那么在某一时刻,树无法再扩展 :即没有可用的边缘顶点,但仍有顶点未被加入生成树。
  • 此时算法可以直接判断:图不连通,不存在最小生成树

11.如果图的边权重可为负, Prim 算法总是能正确求出最小生成树吗?

Prim 算法在边权重可以为负时,仍然能正确求出最小生成树,Prim 是贪心选择 + 安全边定理 :每次选连接当前树与外部、权重最小 的边,不管这条边是正还是负,这条边一定属于某棵 MST

负权边只会让这条边更可能被选中,不会破坏算法正确性

12.令T是由 Prim 算法得到的图G的最小生成树。通过对G增加一个新的顶点和一些新的边,假设新边有权重且新边连接新顶点和图G中的某些顶点,从而得到一个新图Gnew。我们能通过仅对T增加一条新边,就能构造出图Gnew的一棵最小生成树吗?如果回答是,请解释如何得到;如果回答否,请解释为什么不能。

不能保证只加一条边就能得到 G_new 的最小生成树。

  • 原来的图 G,最小生成树是 T。
  • 现在加一个新顶点 v,以及若干条从 v 连到 G 中顶点的新边。
  • 要把 v 接入新的最小生成树,确实只需要一条边(树的性质:加一个点只需一条边)。
  • 但是,原来的最小生成树 T 本身可能不再是新图 G_new 的最小生成树的一部分。

有可能存在这样的新边:它的权重非常小(甚至是负的), 使得替换掉 T 里某条旧边后,整棵生成树的总权重更小。

13.如果连通图的边不含权,如何应用 Prim 算法得到该图的一棵最小生成树? Prim算法是求解该问题的好算法吗?

每条边的权重都看作 1 (或任意相同常数),然后直接正常运行 Prim 算法即可。

因为所有边权相等,任何一棵生成树都是最小生成树(总权重 = n−1)。Prim 会正常选出一棵生成树。

但并不是好算法。 无权图的生成树,只需要保证连通、无环、n-1 条边 。用 BFS 或 DFS 一遍就能得到生成树,时间 O(V+E) ,又简单又快。Prim 本质是带权 MST 算法,用到了优先队列,效率更低、实现更复杂

14.请证明:如果加权连通图的每一个权重都是唯一的,它只具有唯一的最小生成树。

反证

15.设计一个高效的算法来改变最小堆的一个元素值。该算法的时间效率如何?

  1. 定位 到要修改的元素位置 i
  2. 修改 该位置的值为新值 new_val
  3. 修复堆结构(分两种情况):

情况 A:新值 变小了

  • 该结点可能比父亲更小,违反最小堆
  • 向上调整:sift up(上浮)

情况 B:新值 变大了

  • 该结点可能比子女更大,违反最小堆

  • 向下调整:sift down(下沉)

    算法 MODIFY_HEAP(heap, i, new_val):
    old_val = heap[i]
    heap[i] = new_val

    复制代码
      if new_val < old_val:
          SIFT_UP(heap, i)    // 变小,上浮
      else:
          SIFT_DOWN(heap, i)  // 变大,下沉

效率为O(logn)

相关推荐
無限進步D2 小时前
差分算法 cpp
c++·算法·蓝桥杯·竞赛
星空露珠2 小时前
迷你世界UGC3.0脚本Wiki生物模块管理接口 Monster
开发语言·数据结构·算法·游戏·lua
星空露珠2 小时前
迷你世界UGC3.0脚本Wiki世界模块管理接口 World
开发语言·数据库·算法·游戏·lua
阿贵---2 小时前
C++中的装饰器模式
开发语言·c++·算法
放下华子我只抽RuiKe52 小时前
机器学习核心算法全景指南
人工智能·python·深度学习·算法·机器学习·机器人·交互
FluxMelodySun2 小时前
机器学习(二十四) 降维 : MDS降维方法与线性降维方法
人工智能·算法·机器学习
setmoon2142 小时前
C++中的装饰器模式高级应用
开发语言·c++·算法
I_LPL2 小时前
day56 代码随想录算法训练营 图论专题9
算法·图论
m0_528174452 小时前
C++中的装饰器模式实战
开发语言·c++·算法