《算法图解》第八章_贪婪算法_集合覆盖问题

一、贪婪算法介绍

算法基本思路:从问题的某一个初始解出发一步一步地进行,根据某个优化测度,每一步都要确保能获得局部最优解。每一步只考虑一个数据,他的选取应该满足局部优化的条件。若下一个数据和部分最优解连在一起不再是可行解时,就不把该数据添加到部分解中,直到把所有数据枚举完,或者不能再添加算法停止。(摘自 贪婪算法_百度百科

简单直接的描述,就是指每步都选择局部最优解,最终得到的就是全局最优解。

二、引入:集合覆盖问题

假设你办了个广播节目,要让全美个州的听众都收听得到,为此,你需要决定在哪些广播台播出。在每个广播台播出都需要支付费用,因此你试图在尽可能少的广播台播出。现有广播台名单如下:

每个广播台都覆盖特定的区域,不同广播台的覆盖区域可能重叠。

如何找出覆盖全美个州的最小广播台合集呢?下面是解决步骤:

  1. 列出每个可能的广播台集合,这被称为幂集(power set)。可能的子集有2n个。
  2. 在这些集合中,选出覆盖全美50个州的最小集合。

那么问题来了,计算每个可能的广播台子集需要很长的时间。

我们可以尝试使用贪婪算法。

三、算法实现

算法步骤

  1. 选出这样一个广播台,即它覆盖了最多未覆盖的州。即便这个广播台覆盖了一些已覆盖的州(就是重复覆盖),也没有关系。
  2. 重复第一步,直到覆盖了所有的州。

这是一种近邻算法(approximation algorithm)。在获得精确解需要的时间太长时,可以考虑使用近似算法。判断近似算法优劣的标准如下:

  • 速度有多快;
  • 得到的近似解与最优解的接近程度。

因此贪婪算法是一个不错的选择,它们不仅简单,而且通常运行速度很快。在本例中,贪婪算法的运行时间为O(n2),其中n为广播台数量。

代码如下

# 创建一个列表,其中包含要覆盖的州
states_needed = set(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"]) # 传入一个数组,被转换为集合

stations = {}
stations["kone"] = set(["id", "nv", "ut"])
stations["ktwo"] = set(["wa", "id", "mt"])
stations["kthree"] = set(["or", "nv", "ca"])
stations["kfour"] = set(["nv", "ut"])
stations["kfive"] = set(["ca", "az"])

final_stations = set() # 使用一个集合来存储最终选择的广播台

while states_needed:
  best_station = None # 将覆盖了最多的未覆盖州的广播台存储进去
  states_covered = set() # 一个集合,包含该广播台覆盖的所有未覆盖的州
  for station, states in stations.items(): # 循环迭代每个广播台并确定它是否是最佳的广播台
    covered = states_needed & states # 计算交集
    if len(covered) > len(states_covered): # 检查该广播台的州是否比best_station多
      best_station = station # 如果多,就将best_station设置为当前广播台
      states_covered = covered

  states_needed -= states_covered # 更新states_needed
  final_stations.add(best_station) # 在for循环结束后将best_station添加到最终的广播台列表中

print(final_stations) # 打印final_stations

四、小结

  • 贪婪算法寻找局部最优解,企图以这种方式获得全局最优解。
  • 贪婪算法易于实现、运行速度快,是不错的近似算法。
  • 广度优先搜索、迪杰斯特拉算法是贪婪算法。

五、代码部分解读

在上述算法中,有一段代码很有趣

covered = states_needed & states # 计算交集

它是用来进行集合之间的相关计算,在此介绍下并集、交集和差集

  • 并集意味着将集合合并;
  • 交集意味着找出两个集合中都有的元素;
  • 差集意味着将从一个集合中剔除出现在另一个集合中的元素。

下面将举例进行说明

>>> fruits = set(["avocado","tomato","banana"])
>>> vegetables = set(["beets","carrots","tomato"])
>>> fruits | vegetables # 计算并集
{‘carrots‘, ‘tomato‘, ‘avocado‘, ‘beets‘, ‘banana‘}
>>> fruits & vegetables # 计算交集
{‘tomato‘}
>>> fruits - vegetables # 计算差集
{‘avocado‘, ‘banana‘}
>>> vegetables - fruits
{‘carrots‘, ‘beets‘}

由此我们可以看出,集合类似于列表,只是不能包含重复的元素

原文地址:https://www.cnblogs.com/OctoptusLian/p/9190176.html

时间: 2024-10-19 20:47:00

《算法图解》第八章_贪婪算法_集合覆盖问题的相关文章

《算法图解》——第八章 贪婪算法

第八章    贪婪算法 1 简单的贪婪算法 每步都采取最优的做法,每步都选择局部最优解. 2 背包问题 有些情况下,完美是优秀的敌人.如果你只需要找到一个大致解决问题的算法,贪婪算法挺不错,因为实现容易,结果与正确结果相当接近. 练习8.1 你在一家家具公司工作,需要将家具发往全国各地,为此你需要将箱子装上卡车.每个箱子的尺寸各不相同,你需要尽可能利用每辆卡车的空间,为此你将如何选择要装上卡车的箱子呢?请设计一种贪婪算法.使用这种算法能得到最优解吗? 选择可以装入卡车中最大的箱子,不断重复,直到

基本数据类型(字符串_数字_列表_元祖_字典_集合)

基本数据类型(字符串_数字_列表_元祖_字典_集合) 1.字符串 2.数字 除了布尔类型外,int.long.float和complex都可以使用的运算为:加.减.乘.除.整除.幂运算和取余 3.列表和元组 列表的内容可变,可以包含任意对象,使用中括号表示.元组的内容不可变,可以包含任意对象,使用圆括号表示.元组 1 l = [1, 2, 3, '4', '5'] # 列表 2 l = list((1, 2, 3, '4', '5')) 3 4 t = (1, 2, 3, '4', '5') #

算法基础_递归_求杨辉三角第m行第n个数字

问题描述: 算法基础_递归_求杨辉三角第m行第n个数字(m,n都从0开始) 解题源代码(这里打印出的是杨辉三角某一层的所有数字,没用大数,所以有上限,这里只写基本逻辑,要符合题意的话,把循环去掉就好): import java.util.Scanner; /** * 求杨辉三角第m层第n个数字 * @author Administrator * */ public class Demo05 { public static int f(int m,int n) { if(n==0)return 1

《算法图解》代码实现和改进

<算法图解>代码实现和改进 请随意观看表演 二分查找 数组和链表 递归 递归条件和基线条件 快速排序 散列表 广度优先搜索 狄克斯特拉算法 贪婪算法 二分查找 def bin_search(list,item): low = 0 high = len(list) - 1 while low<=high: mid = (low+high)//2 #得到中间值 guess = list[mid] if guess==item: return mid elif guess>item: h

程序备忘_弱磁_高压异步

程序备忘_弱磁_高压异步 2017-03-21 18:13 34人阅读 评论(0) 收藏 举报  分类: 程序备忘(42)  算法(39)  高压变频(36)  版权声明:本文为博主原创文章,可以转载

基本数据类型-列表_元组_字典

基本数据类型-列表_元组_字典 一.列表(list)书写格式:[] 1 #通过list类创建的 2 3 li = [1, 12, 9, "age", ["刘正文", ["19", 10, ],"庞麦郎"], "ales", True] 1.列表格式2.列表中可以嵌套任何类型 中括号起来 ,分割每个元素 列表中的元素可以是 数字,字符串,列表,布尔值....所有的都能放进去 "集合" ,内

《啊哈!算法》 第八章 更多精彩的算法

第一节  镖局运镖-图的最小生成树 所谓最小生成树,就是在一个具有N个顶点的带权连通图G中,如果存在某个子图G',其包含了图G中的所有顶点和一部分边,且不形成回路,并且子图G'的各边权值之和最小,则称G'为图G的最小生成树. 最小生成树的三个性质 最小生成树不能有回路 最小生成树可能是一个,也可能有多个 最小生产树的边的个数等于顶点的个数减一 Kruskal 算法(选边法) 其核心思想是:首先按照边的权值进行从小到大排序,每次从剩余的边中选择权值较小且边的两个顶点不在同一个集合的边(就是不会产生

《算法图解》+ 《我的第一本算法书》+资料PDF学习

<我的第一本算法书>没有枯燥的理论和复杂的公式,而是通过大量的步骤图帮助读者加深对数据结构 原理和算法执行过程的理解,便于学习和记忆. 下载:https://pan.baidu.com/s/1poq0e2siuvR1Re5pEIkBnQ <我的第一本算法书>高清PDF,210页,彩色配图,带书签目录,文字可以复制. <我的第一本算法书>采用大量图片,通过详细的分步讲解,以直观.易懂的方式展现了7个数据结构和 26个基础算法的基本原理.第1章介绍了链表.数组.栈等7个数据

《算法图解》全本PDF下载附百度云链接

作者使用Python和图画来解释算法,找了好久才找到PDF版本,末尾附百度云链接~ 作者[美]Aditya Bhargava 译者袁国忠 类别 出版 / 非虚构 出版社人民邮电出版社 / 2017-03 提供方图灵社区 字数约 72,000 字 ISBN9787115447630 作品简介 本书示例丰富,图文并茂,以让人容易理解的方式阐释了算法,旨在帮助程序员在日常项目中更好地发挥算法的能量.书中的前三章将帮助你打下基础,带你学习二分查找.大O表示法.两种基本的数据结构以及递归等.余下的篇幅将主