类动态规划求解较小规模的最大团问题(Python实现)
1.图:由点、边(点与点之间连线),组成的集合,如点集V=[0,1,2,3,4],边集E=[[1,3,4],[2,3,4],[4],[4],[]],则(V,E)就是一个图,其表达的意思如下:
该图中含有5个端点,分别为0,1,2,3,4,这些点存在V中,如端点1对应V[1]=1端点之间会连着线,称为边,如1和2之间连的边,就对应E中E[1]=[2,3,4]的元素2,如0和4之间连的边就对应E[0]=[1,3,4]含有元素4(E[4]=[]不含元素0是因为0<4,只需在E[0]中记录了4即可)
2.团:一个图可能会有多个团,团是V的子集,记为集合G,且保证G中任意两点之间都有连线如G=[1,3,4],其中1,3,4三点两两相连,一个图的包含元素最多的团称为最大团。
最大团问题网上的求解办法非常多(本身其实这是一个NP问题),这次比较特殊的地方是要求使用Python,而且如果有多个解要输出多个具体的解(也就是说中间结果要记录),总之题目描述就是:
输入:V,E
输出:最大团数目,最大团集合(如果有多个要求全部输出)
采用动态规划的思想就是将问题分段求解,可以将问题分为5段:求含有一个、两个、三个、四个、五个元素的团,其中含有N元素的团必包含含有N-1个元素的团,故只需在上一段问题的答案的基础上,尝试给团添加新的元素。
另外,实际上例如求解出两个元素的团,如本题中的[0,1],[0,3],[0,4],[1,2],[1,3],[1,4],[2,4],[3,4]时,已经裁掉了[0,2],[2,3]的下面的解了,所以也算有一点剪枝的意思。接下来直接看代码实现:
#-*- coding=utf-8 -*- V=[0,1,2,3,4]
# E=[[1,3,4],[2,4],[4],[4],[]]
E=[[1,3,4],[2,3,4],[4],[4],[]] ###较小规模的最大团问题
import copy def isConnected(u,v): if u==-1 or v==-1:###虚拟节点-1与所有的节点都相连 return 1 edge_points=E[u] if v in edge_points: return 1 else: edge_points = E[v] if u in edge_points: return 1 else: return 0 def isConnectedAll(clique,v):#判断v是否和clique中所有节点相连 flag = 1 for i in clique: if not isConnected(i,v): flag =0 break return flag class Step: def __init__(self): self.maxClique = [] #计算完毕时的解集(每个阶段的实际结果) self.cliqueList = []#计算时用的解集 self.maxnC = 0 def maxCliqn(self):#计算当前阶段最大值 max = 0 for clique in self.cliqueList: if max < len(clique): max = len(clique) return max def isNew(self,clique): #判断一个解组合是否已经存在于该阶段的实际解集中 for cl in self.maxClique:#针对每个已存入的解集进行判断 diff = list(set(clique).difference(set(cl))) # 取解的差集 if (len(diff)): continue #差集不为空,说明不同,继续循环 else: return False # 差集为空,说明有个解完全一样,返回False return True def updateMaxClique(self):#更新当前阶段的最大团数目 self.maxnC= self.maxCliqn() for clique in self.cliqueList: if(len(clique)==self.maxnC): if self.isNew(clique): self.maxClique.append(clique) if __name__ == "__main__": n = len(V) solutions = {} for i in range(0,n): solutions[i]= Step() #初始化n个阶段 for v in V: a = [] a.append(v) solutions[0].cliqueList.append(a) solutions[0].updateMaxClique()#设置初始值 for i in range(1,n): #cliqList= solutions[i-1].maxClique preData = solutions[i-1] cliqList = preData.maxClique preMax = preData.maxnC for clique in cliqList:#针对前一阶段的每个clique求解 for v in V:#针对所有的点 tempclique = copy.deepcopy(clique)##必须使用深拷贝 if not v in tempclique:#如果该clique没有包含v if isConnectedAll(tempclique,v):#如果v与clique的所有点相连 tempclique.append(v)#加入该点 solutions[i].cliqueList.append(tempclique)#加入这个解 solutions[i].updateMaxClique() if not len(solutions[i].maxClique):#如果已经找不到更多的点加入团,那么后面的也不用计算了(比如找不到4个的团,那么5个的团也没必要再尝试计算) break for i in range(0,n): print("step"+str(i)+": "+str(solutions[i].maxClique)) for i in range(n-1,-1,-1): solution = solutions[i] if len(solution.maxClique): maxn = solution.maxnC print("最大团数目是"+ str(maxn)+"个") print("最大团为:") print(solution.maxClique) break
值得注意的一点是,python里面直接用赋值符号得到的对象实例是使用的浅拷贝,跟java类似,所以要使用copy模块的deepcopy函数来建立临时列表做各种判断以及修改添加(因为我也对python不太熟悉,而且原来没仔细考虑过拷贝引用带来的问题,中间错了好一阵)。
输出:
V=[0,1,2,3,4] E=[[1,3,4],[2,4],[4],[4],[]]
step0: [[0], [1], [2], [3], [4]]
step1: [[0, 1], [0, 3], [0, 4], [1, 2], [1, 4], [2, 4], [3, 4]]
step2: [[0, 1, 4], [0, 3, 4], [1, 2, 4]]
step3: []
step4: []
最大团数目是3个
最大团为:
[[0, 1, 4], [0, 3, 4], [1, 2, 4]]
E=[[1,3,4],[2,3,4],[3,4],[4],[]]
step0: [[0], [1], [2], [3], [4]]
step1: [[0, 1], [0, 3], [0, 4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
step2: [[0, 1, 3], [0, 1, 4], [0, 3, 4], [1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
step3: [[0, 1, 3, 4], [1, 2, 3, 4]]
step4: []
最大团数目是4个
最大团为:
[[0, 1, 3, 4], [1, 2, 3, 4]]
E=[[1,3,4],[2,3,4],[4],[4],[]]
step0: [[0], [1], [2], [3], [4]]
step1: [[0, 1], [0, 3], [0, 4], [1, 2], [1, 3], [1, 4], [2, 4], [3, 4]]
step2: [[0, 1, 3], [0, 1, 4], [0, 3, 4], [1, 2, 4], [1, 3, 4]]
step3: [[0, 1, 3, 4]]
step4: []
最大团数目是4个
最大团为:
[[0, 1, 3, 4]]
其他的也没怎么测试了,如果有bug,各位读者看着改改吧= =。提供一个思路,仅作参考。
类动态规划求解较小规模的最大团问题(Python实现)相关推荐
- 使用动态规划求解算法问题的五大特点总结(附基于Python的参考代码)
什么样的问题应使用动态规划求解 前言 一.求"最"优解问题(最大值和最小值) 1. 乘积最大子数组 问题描述 示例 题目分析 参考代码 2. 最长回文子串 问题描述 示例 题目分析 ...
- 区间类动态规划(dp)
一.问题引入 给定长为n的序列a[i],每次可以将连续一段回文序列消去,消去后左右两边会接到一起, 求最少消几次能消完整个序列,n≤500.与线性模型不同,这里消去的顺序是任意的,且消完后左右会接起来 ...
- python实现动态规划求解给定矩阵的和最大的子数组(矩阵中数字正负均存在)
本篇博文比较简单没有太多实际意义,只是为了练习一下,动态规划我并不熟悉,也是刚处于学习的阶段. 问题: 给定一个指定的矩阵,维数小于1000,在矩阵的所有子数组中寻找具有最大和的子数组求和输出. 思路 ...
- 1008-----算法笔记----------0-1背包问题(动态规划求解)
1.问题描述 给定n种物品和一个背包,物品i的重量是wi,其价值为vi,背包的容量为C.问:应该如何选择装入背包的物品,使得装入背包中物品的总价值最大? 2.问题分析 上述问题可以抽象为一个整数规划问 ...
- 子串、子数组与子序列类型问题的动态规划求解(Leetcode题解-Python语言)
一般来说,子串和子数组都是连续的,而子序列是可以不连续的,遇到子序列问题基本上都是用动态规划求解. 53. 最大子数组和(剑指 Offer 42. 连续子数组的最大和) class Solution: ...
- 提高篇 第五部分 动态规划 第1章 区间类动态规划
https://blog.csdn.net/guoyangfan_/article/details/81162689 动态规划(四)--区间型动态规划_布纸所云-CSDN博客 [算法详解]区间动态规划 ...
- 提高篇 第五部分 动态规划 第4章 状态压缩类动态规划
例1 骑士(Sgu223) 1592:[例 1]国王 信息学奥赛一本通(C++版)在线评测系统 https://blog.csdn.net/guoyangfan_/article/details/82 ...
- python用动态规划求删除路径_Python | 动态规划求解TSP
解题思路主要有两部分: i为当前节点(城市),S为还没有遍历的节点(城市集合),表示从第i个节点起,经历S集合中所有的点,到达终点的最短路径长度. 回溯找到最优的路径,需要将S集合一一对应一个数字(类 ...
- 动态规划求解所有字符的组合数
一,问题描述 给定若干个字符,求解 这些字符能够表示的最多组合个数.比如{'a','b','c'} 一共有七种组合.(每种组合没有重复的字符 且 组合的种数与顺序无关,如 ab 和 ba 是同一种组合 ...
- 01背包问题 动态规划求解方法 动态方程的详细解释 能理解的解释(附python代码)
01背包问题属于组合优化问题:假设你要出门旅游,你现在有一个书包,这个书包的容量(capacity)有限,有很多物品如牙刷.防晒霜.雨伞.水杯等等,但书包装不下所有物品,因此我们必须有所取舍.那么通常 ...
最新文章
- 单端测序(Single end)和双端测序(Pair end和Mate pair)
- Linux 内核详解以及内核缓冲区技术
- 磁盘 I/O 的概念
- 构建之法第四章读后感
- 韩国讨论到 2020 年拥抱开源操作系统
- android8camera,[Android8.0/9.0/10]Camera:外接 USB 摄像头
- 选择比努力更重要,面试新公司,从哪些细节能判断公司的前途?项目的好坏?...
- pat 乙级 1018 锤子剪刀布(C++)
- 在CentOS6.5上安装Tomcat6
- dpkg命令_Linux 命令学习神器!命令看不懂直接给你解释!
- (转)认识原型对象和原型链
- python 用户登录判断
- 全栈工程师可以分为哪几类?
- Android File存储
- ADL之UI初预览 AJAX 开发
- 8款功能强大的最新HTML5特效实例
- 一篇文章带你大致了解5G关键技术、协议架构、网络优化覆盖、业务测试与验证
- java中 是什么意思_java中?:是什么意思
- 学计算机r7000和y7000哪个好,联想拯救者r7000p和y7000p哪个好-联想拯救者r7000p和y7000p评测对比...
- CSAPP实验2:bomblab
热门文章
- 计算机主板常见故障检修,主板常见故障检查与维修
- 类似911的代理ip,911代理的官网,yilu代理软件,911s5替代软件海外代理平台哪里有?
- 如何用LOTO示波器TDR方法测试电线长度?
- web前端开发分享-css,js进阶篇
- 计算机网络工资如何计算,2019 税后工资计算器,能够准确算薪
- Zabbix 3.0 监控Web [七]
- PHP序列化与反序列化
- 【HTB系列】靶机Chaos的渗透测试详解
- leetcode-739.每日温度-单调栈
- TeamViewer突破地域限制,解决办公难题