集合的应用----集合覆盖分析
来源:互联网 发布:大学生网络文明调查 编辑:程序博客网 时间:2024/05/17 20:54
集合覆盖问题(Set Covering Problem,简称SCP)是运筹学研究中典型的组合优化问题之一,工业领域里的许多实际问题都可建模为集合覆盖问题,如资源选择问题、设施选址问题(移动基站的选址、物流中心的选址)等。
问题: 给定一个集合S,集合P是由集合S的子集A1到An组成,集合C由集合P中的一个或者多个自己组成。如果S中的每个成员都包含在C的至少一个自己中车成为集合C覆盖S。此外,C包含的P的子集应该越少越好。
这里给出针对集合覆盖的算法的一种近似算法(当然不一定是最优解)。算法原理:从集合P中选择一个子集An(An是包含集合S元素最多的子集),然后P中选择一个自己Am(Am是包含An中未包含集合S中的元素中最多的子集)......依次类推,直到全部覆盖。
案例:求12种技能集合S = {a,b,c,d,e,f,g,h,i,j,k,l}的最佳覆盖集,考虑到现有7名待选选手集合P={A1,A2......A7}。P种选手的技能集合如下为:A1={a,b,c,d} ,A2={e,f,g,h,i},A3={j,k,l},A4={a,e},A5={b,f,g},A6={c,d,g,h,k,l},A7={l}.最佳覆盖集合应该为C={A1,A2,A3}。下面依照算法来推导:
1、选出覆盖集合S最多的一个子集:(成员个数最多)A6 ;差集 M= {a,b,e,f,i,j};
2、从剩余集合中选出覆盖差集M最多的一个子集:A2;M 与 M与A2交集的差集 {a,b,j};
3、依次来推 .....A1 {j};
4、..............A3;
这样得到的集合C = {A6,A2,A1,A3};
头文件:
/* cover.h */#ifndef COVER_H#define COVER_H#include "set.h"/* 通过KEY值为子集定义一个结构体*/typedef struct KSet_ {int key;/*集合P中子集的下表*/Set set;/*集合*/}Kset;/*函数接口*/int cover(Set *members,Set *subsets,Set *covering);#endif
函数实现:
/*cover.c*/#include <stdlib.h>#include "../include/cover.h"#include "../include/list.h"#include "../include/set.h"int cover(Set *members,Set *subsets,Set *covering){Set intersection;/*并集*/Kset *subset;/*子集*/ListElmt *member, *max_member;void *data;int max_size = 0;/*初始化集合 cover */set_init(covering,subsets->match,NULL);/* 依次选出集合中覆盖最多元素的子集*/ while (set_size(members) > 0 && set_size(subsets) > 0){max_size = 0;for (member = list_head(subsets); member != NULL; member = list_next(members)){/*查找交集*/if (set_intersection(&intersection,&((KSert *)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 ; member = list_next(member)){data = list_data(member);if (set_remove(members,(void **)&data) ==0 && member->destroy != NULL){members -> destroy(data);}}/*将找到的子集从subsets中删除*/if (set_remove(subsets,(void **)&subset) != 0){return -1;}}/*如何循环完毕members中可能存在仍有未找到成员 */if (set_size(members) >0){return -1;}}
函数实现中可能用来单链表中定义的函数接口;具体可以去专栏中的链表中去查看。
- 集合的应用----集合覆盖分析
- 8、集合应用-集合覆盖问题
- 集合覆盖
- 集合覆盖
- Python的应用集合
- 集合的面试应用
- 集合类的应用
- 集合Properties的应用
- ArrayList 集合的应用
- Properties集合的应用
- python集合的应用
- 对List<E>集合中添加新元素覆盖之前的元素问题的分析
- 集合覆盖模型
- 集合应用
- java集合框架 arrayblockingqueue应用分析
- HTML集合属性的应用
- 集合类Vector的应用
- 贪吃蛇--集合的应用
- 一步一步走进Linux HOOK API(六)
- 我的gentoo,告别scim,转用fcitx
- ubuntu重启不清除 /tmp 设置
- How to unpack a tar file in windows
- 一步一步走进Linux HOOK API(七)
- 集合的应用----集合覆盖分析
- js、jquery、动态添加option项
- struts2 从一个action 跳转到另一个action的两种方法
- 大数据量处理方法总结
- python list operation
- SSH框架整合步骤
- storm安装注意事项记录
- linux中nmap的用法
- ANI文件格式