Answers:
我假设您希望指纹尽可能小。这就是“ 命中集”问题:对于每个人,列出X而不是此人喜欢的所有书籍的列表。然后,目标是从每个列表中至少选择一本书。问题是NP难题,因此您不能期望找到一个总是在多项式时间内最优解决问题的算法。贪婪算法在理论上存在最坏情况下的局限性,但在实践中通常效果不错。如果要最佳地求解,则整数线性规划求解器应能够求解多达1000甚至10000本书籍的实例。如果您提供有关实例大小和结构的更多详细信息,我们可以建议其他方法。
这不是一个特别聪明的算法,但是它是多项式,我认为它应该可以工作。采取任何设置。对于此集合中的每个元素,计算不包含该元素的剩余集合的数量,并记住包含这些元素的集合。选择计数最高的元素,然后重做其余元素的计数,而忽略缺少刚选择的元素的集合。继续进行,直到所有剩余的设置都被排除在考虑之外。
例如:让,乙= { 2 ,3 ,4 },c ^ = { 2 ,4 ,6 },和d = { 1 ,3 ,5 }。然后我们有计数c 1 = 2,c 2 = 1和c 3 = 1。我们选择1,消除不包含集合和C的集合;重做计数,我们有c 2 = 1和c 3 = 0。我们选择2作为下一个元素,并从考虑中删除D。我们现在做的,我们的“指纹”是集合{ 1 ,2 }。编辑:要完成这个例子,你应该得到的其他指纹套出来为{ 3 ,4 },{ 6 }和{ 5 }。
我没有考虑太多,但是从直观上看,它似乎应该起作用。这个想法是贪婪地将覆盖最多未发现集的项目作为指纹集的下一个元素。
fingerprint books
让我在python代码上进行演示:
%persons with books they like (it could also be a list or a set)
joe='ABCD'
andy='CDG'
frank='AHX'
anna='HAYZ'
matt='ACH'
%just transformation form variables, to names
names={joe:"Joe",andy:"Andy",frank:"Frank",anna:"Anna", matt:"Matt"}
%the map, from books to persons who like this book
books={}
%for each person
for p in names:
%go through his liked books
for book in p:
%if book is already in the map, then append the person
if book in books:
books[book].append(names[p])
else:
%if not, then create a new book, and append the current person
books[book]=[names[p]]
%create the fingerprint map (from person to books he likes)
fingerprint={}
%for each person create an empty list
for p in names:
fingerprint[names[p]]=[]
%for each book in the map
for book in books:
%if only one person likes this book, then it must be a part of his fingerprint
if len(books[book])==1:
fingerprint[books[book][0]].append(book)
print fingerprint
代码显示:
{'Frank': ['X'], 'Matt': [], 'Andy': ['G'], 'Joe': ['B'], 'Anna': ['Y', 'Z']}
这是OP(初次提交时未注册,所以现在我不能正确评论)。非常感谢您的反馈-原始的贪婪算法解决方案使我朝着正确的方向前进。我正在处理的总空间涉及100个个体和1000个“书”-如果整数编程方法可行,那么我想听听更多。