集合覆盖是一种优化求解问题,对很多组合数学和资源选择问题给出了很好的抽象模型。 问题如下:给定一个集合S,集合P由集合S的子集A1到An组成,集合C由集合P中的一个或多个子集组成。如果S中的每个成员都包含在C的至少一个子集中则称集合C覆盖集合S。此外,C包含的P的子集越少越好。

设想从一大群选手中挑选人员组建一支队伍,每名选手都拥有特定的技能组合。目标是组建出一只最小的队伍,使得队伍整体拥有一组特定的技能组合。也就是说,对于队伍整体所需要的技能,队伍中至少有一名选手必须拥有这项技能。假定S为队伍所必须拥有的技能集合,P为所有待选选手的技能集合。从P中挑选出一些技能组合以构成C,C必须覆盖S中所要求的所有技能。重要一点,我们选择的选手数量必须尽可能少。

针对集合覆盖的算法是一种近似算法,它并不总是获得最优解。该算法的工作原理是:

不断从P中选出一个集合,使其能够覆盖S中最多的成员数量。换句话说,该算法每次都尝试尽可能早覆盖S中更多的成员,因此该算法采用了贪心法的思路。由于每个集合都是从P中选出的,如果P被移除,则它的成员也将从S中移除。当P中剩余的成员没有任何集合能够覆盖S中的成员时,此时覆盖集合C就完成了。

让我们看看对于12种技能的集合S={a,b,c,d,e,f,g,h,i,j,k,l}的最佳覆盖集。现在考虑有7名待选选手的集合P={A1,...A7}。P中选手拥有的技能集合为:A1={a,b,c,d},A2={e,f,g,h},A3={j,k,l},A4={a,e},A5={b,f,g},A6={c,d,g,h,k,l},A7={l}。最佳覆盖集应该是C={A1,A2,A3}。这里给出的算法选择的集合是C={A6,A2,A1,A3}(见图1)。

集合覆盖问题的函数实现

我们使用函数cover,该函数在集合P的子集A1~An中挑选出能够覆盖集合S的近似最优解。该函数有3个参数:

1、members是待覆盖的集合S;

2、subsets是集合P中的子集;

3、covering作为返回的覆盖集C。

该函数将修改所传入的3个参数,因此在调用该函数时,如果有必要话应该保存一份参数的拷贝。

函数执行过程:开始时,covering通过调用set_init先得到初始化。

我们使用循环进行迭代,只要members中还有未覆盖的成员,且subsets中的子集还没有挑选完,最外层的循环就得继续迭代。

在这个循环中,每次迭代时它都在subsets中找出能够覆盖到members的最大交集。

然后它将这个集合加到覆盖集covering中并把它的成员从members中移除(因为这些成员已经被覆盖,下一次迭代将判断剩余的成员能否被覆盖)。在循环的最后,将所选择的这个集合从subsets中移除(已经选中的要移除)。如果最外层的循环因为members不为空而终止迭代,则表示subsets中的集合不可能满足完全覆盖members的要求。同样,如果在迭代期间subsets中的成员无法与members的成员形成交集,则同样表示subsets中的成员无法满足完全覆盖members的要求。函数cover如果找到了一个完全覆盖解,该函数返回0,参数covering指向这个完全覆盖解;如果不可能实现完全覆盖,则返回1;其他情况返回-1。

cover的复杂度为O(m3),这里的m代表members集合中的初始成员个数。在最坏的情况下,对于members中的每一员,subsets中都只有唯一一个子集与之对应,此时的复杂度是O(m3)。在这种情况下,subsets有 m个子集,set_intesection以O(m)的复杂度执行,因为当计算和members求交集时,subsets的每个子集都只有唯一一个个成员需要遍历。因此cover的内层循环是O(m2)的,而这个循环要执行m次。

示例1:集合覆盖问题的头文件

#ifndef COVER_H#define COVER_H#include"set.h"typedefstructKSet_

{void *key;

Setset;

}KSet;int cover(Set *member, Set *subsets, Set *covering);#endif

示例2:集合覆盖问题的函数实现

#include #include"cover.h"#include"list.h"#include"set.h"

int cover(Set *members, Set *subsets, Set *covering)

{

Set intersection;

KSet*subset;

ListElmt*member,*max_member;void *data;intmax_size;/*初始化覆盖集covering*/set_init(covering,subsets->match,NULL);while(set_size(members)>0 && set_size(subsets)>0)

{/*找到能够覆盖最多members成员的子集*/max_size= 0;for(member = list_head(subsets);member!=NULL;member=list_next(member))

{if(set_intersection(&intersection, &((KSet *)list_data(member))->set, members) != 0)return -1;if(set_size(&intersection)>max_size)

{

max_member=member;

max_size= set_size(&intersection);

}

set_destroy(&intersection);

}/*如果不存在交集,那么就不可能有覆盖集*/

if(max_size==0)return 1;/*将被选到的子集插入覆盖集covering中*/subset= (KSet *)list_data(max_member);if(set_insert(covering,subset) != 0)return -1;/*从members中移除已经被覆盖的元素*/

for(member=list_head(&((Kset *)list_data(max_member))->set);member !=NULL;

list_next(member))

{

data=list_data(member);if(set_remove(members,(void **)data)== 0 && members->destroy !=NULL)

members->destroy(data);

}/*从子集集合中删除已经被选用的子集*/

if(set_remove(subsets,(void **)&subset) != 0)return -1;

}/*如果members中仍然存在未被覆盖的元素,那么也不可能实现完全覆盖*/

if(set_size(members)>0)return -1;return 0;

}

集合覆盖模型例题_集合实例(集合覆盖)相关推荐

  1. 集合覆盖模型例题_在打CodeForces的过程中发现的一个小模型

    不久前的Grakn Forces 2020上,我想出了这个方法,我本来以为这个模型不会很常见.然而,今天的CodeForces #679 Div2上,我第二次碰到了可以用这个模型解决的问题,气人的是, ...

  2. js删除两个集合中共同元素_多个集合中的共同和独特元素

    js删除两个集合中共同元素 本周,我们将暂时中断较高级别的问题和技术文章,以解决我们中许多人可能面临的一些代码问题. 没什么花哨的或太辛苦的,但是有一天它可能会节省您15分钟的时间,偶尔回到基础上也很 ...

  3. 两个集合相等的例题_集合的相等答案

    分析: 由 题设知对于集合 N 中的函数 f ( x ) 的定义域为 [a , b ] , 对应的 f ( x ) 的值域为 N=M=[a , b ] . 由函数 , 知 f ( x ) 是增函数. ...

  4. python如何移动文件却不覆盖现有文件_解决python不能覆盖文件内容的方法

    解决python不能覆盖文件内容的方法 发布时间:2020-07-15 11:42:17 来源:亿速云 阅读:62 作者:清晨 这篇文章将为大家详细讲解有关解决python不能覆盖文件内容的方法,小编 ...

  5. Java学习笔记17:Java_Set集合_TreeSet集合_二叉树_HashSet集合

    文章目录 1.Set集合 1.1Set集合概述和特点[应用] 1.2Set集合的使用[应用] 2.TreeSet集合 2.1TreeSet集合概述和特点[应用] 2.2TreeSet集合基本使用[应用 ...

  6. ProE模型导入Adams视频教程大集合【转载龙之殿网站】

    引用 Baker 的 ProE模型导入Adams视频教程大集合[转载龙之殿网站] ProE模型导入Adams视频教程大集合 步骤如下: 1.在PROE中建好模型 2.   设置PROE单位参数为MMk ...

  7. 最小割 ---- 集合冲突模型 ----- P1646 [国家集训队]happiness

    题面: 高一一班的座位表是个n*m的矩阵,经过一个学期的相处,每个同学和前后左右相邻的同学互相成为了好朋友.这学期要分文理科了,每个同学对于选择文科与理科有着自己的喜悦值,而一对好朋友如果能同时选文科 ...

  8. 最小割 ---- 集合冲突模型 ---- AGC038 F - Two Permutations[详解]

    题目链接 题目大意: 给出两个排列P,QP,QP,Q.要求构造两个排列A,B.A,B.A,B. 要求:AiAiAi要么等于iii,要么等于PiPiPi;BiBiBi要么等于iii,要么等于QiQiQi ...

  9. 最小割 ---- 集合冲突模型

    集合冲突模型 1.问题形式 有 n 个物品和两个集合 S,T.将一个物品放入 S 集合会花费 ai,放入 T 集合会花费 bi.还有若干个形如 u,v,w 限制条件,表示如果 u 和 v 同时不在一个 ...

  10. java 数组集合转换_Java 实例 – 集合转数组

    Java 实例 - 集合转数组 以下实例演示了如何使用 Java Util 类的 list.add() 和 list.toArray() 方法将集合转为数组: /* author by w3cscho ...

最新文章

  1. android百度地图轨迹实现,android 获取GPS经纬度在百度地图上绘制轨迹
  2. [转] 视频直播前端方案
  3. [二叉树] 二叉树中的最大路径和---leetcode124
  4. Linux学习:第四章-vi编辑器
  5. 20199计算机二级java答案_计算机二级Java练习题-2019.9
  6. 自己动手做聊天机器人 一-涉及知识【转】
  7. idea中使用git直接提交本地写好的代码
  8. cpu利用率低linux,linux计算,cpu 利用率超低,如何处理?
  9. 曝光!人工智能行业薪酬到底有多高?
  10. 2021-08-01 Python-爬虫练手:爬取上千张“萌妹子“网美图
  11. 输入法编程之 光标跟随
  12. python股票回测_从啥都不会试着用python做均线回测--1
  13. Logistic 回归的决策边界
  14. 手机通过蓝牙与电脑共享网络
  15. Java 1082 射击比赛
  16. 台式计算机怎么进入bios,小编告诉大家hp台式机怎么进bios
  17. LLVM之父Chris Lattner:为什么我们要重建AI基础设施软件
  18. lambda函数引用学习记录
  19. 长城汽车能否冲破价格战“困局”?
  20. 转正后的一点工作体会

热门文章

  1. 计算机导论的答案,计算机导论答案
  2. 性能分析26-tomcat优化P61
  3. rails中关于carrierwave、kaminari、roo组件分享
  4. 分页插件之--kaminari
  5. 百度、高德、谷歌、火星、wgs84(2000)地图坐标相互转换的JS实现
  6. app第三方支付测试点
  7. java pow_Java中Math.pow()的用法
  8. apk逆向思路_逆向练手——从一个apk简单逆向看消息摘要算法
  9. 图片格式与设计那点事儿
  10. python手写板_Python3使用PyQt5制作简单的画板/手写板的代码详解