贪婪算法:每步都选择局部最优解,最终得到的就是全局最优解。(并非在任何情况下都有效)
1 集合覆盖问题
假如你举办了个广播节目,需要全美50个洲都能收听。
每个广播台都覆盖特定区域,不同广播台覆盖区域可能重叠。
如何找出覆盖这50个洲的最小广播台集合呢?
使用贪婪算法得到近似解:
- 选出一个覆盖了最多的未覆盖洲的广播台。即使覆盖了一些已覆盖的洲也没关系。
- 重复第一步,直到覆盖所有洲。
这是一种近似算法,判断优劣标准如下:
- 速度有多快
- 得到的近似解与最优解的近似程度
准备工作:
1.集合。
集合类似于列表,但同样的元素只能出现一次。
arr = [1,2,2,3,3,4]#创建列表
print(set(arr))#将列表转化为集合
结果如下:
集合的并集,交集,差集(从一个集合中剔除出现在另一个集合中的元素):
fruits = set(["avocado","tomato","banana"])#传入数组,被set()函数转化为集合
vegetables = set(["beets","carrots","tomato"])
print(fruits | vegetables)#并集
print(fruits & vegetables)#交集
print(fruits - vegetables)#差集
结果:
2.创建一个列表,包含要覆盖的洲:
states_needed = set(["mt","wa","or","id","nv","ut","ca","az"])
可供选择的广播台清单,用散列表来表示,键为广播台名称,值为广播台覆盖的洲:
stations = {}
stations["kone"] = set(["id","nv","ut"])
stations["ktow"] = set(["wa","id","mt"])
stations["kthree"] = set(["or","nv","ca"])
stations["kfour"] = set(["nv","ut"])
stations["kfive"] = set(["ca","az"])
用一个集合存储最终选择的广播台:
final_stations = set()
遍历所有广播台,从中选择覆盖了最多的未覆盖洲的广播台。将这个广播台存储在best_stations中:
best_station = None
states_covered = set()#包含该广播台覆盖的所有未覆盖的洲
for station, states_for_station in stations.items():
covered = states_needed & states_for_station#包含同时出现在states_needed和states_for_station中的洲,即交集
if len(covered) > len(states_covered):
best_station = station
states_covered = covered
不断循环,直到 states_needed为空。完整代码:
states_needed = set(["mt","wa","or","id","nv","ut","ca","az"])
stations = {}
stations["kone"] = set(["id","nv","ut"])
stations["ktow"] = 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_for_station in stations.items():
covered = states_needed & states_for_station#包含同时出现在states_needed和states_for_station中的洲,即交集
if len(covered) > len(states_covered):
best_station = station
states_covered = covered
states_needed -= states_covered
final_stations.add(best_station)
print(final_stations)
结果: