联盟搜索算法
Coalition Search Algorithm
我正在寻找一种用C, c++, Python或Java实现的算法,该算法计算n代理的获胜联盟集,其中每个代理具有不同的票数。我很感激任何提示。谢谢!
换句话说,你有一个数组X[1..n]
,你想要它的所有子集sum(subset) >= 1/2 * sum(X)
,对吧?
这可能意味着整个集合都符合条件。
之后,你可以去掉任何一个有X[k] < 1/2 * sum(X)
的元素k
,这样的一个联盟也可以作为一个答案。
之后,可以一个接一个地删除元素,直到删除到和的一半时停止。
这是显然不是最有效的解决方案:你不想放弃k1=1,k2=2
,如果你已经尝试过k1=2,k2=1
-但我相信你可以处理这个
通过递归地将其分为两种情况来解决这个问题是很好的:找到所有获胜的"联盟",包括最后一个"代理"和所有没有最后一个"代理"的"联盟"。现在,对于这些子问题中的每一个都可以应用相同的逻辑,在包含最后一个"代理"的情况下,目标票数会更低。当目标投票数小于或等于零,或者没有更多的代理剩余时,停止递归。
请注意,在这样的算法中,根据投票数排序代理是有益的。
implmentation例子:
from itertools import combinations
def _winning_coalitions(agents, target_votes):
"""recursive solving function
@param agents: sequence of (name, votes) pairs
@param target_votes: minimum number of votes for a coalition
"""
if target_votes <= 0:
# stop the recursion
for coalition_size in range(len(agents)+1):
for coalition in combinations(agents, coalition_size):
yield coalition
elif not agents:
pass # no agents, so no possible coalitions
else:
agent_name, agent_votes = agents[-1]
agents = agents[:-1]
for coalition in _winning_coalitions(agents, target_votes-agent_votes):
yield ((agent_name, agent_votes),) + coalition
if sum([votes for (name, votes) in coalition]) >= target_votes:
yield coalition
def winning_coalitions(agents):
"""find all coalitions with at least target_votes combined votes
@param agents: dictionary of the form: name -> number of votes
"""
target_votes = (sum(agents.values())-1)//2+1
agents = sorted(agents.items(), key=operator.itemgetter(1))
coalitions = _winning_coalitions(agents, target_votes)
return sorted([sorted([name for (name, votes) in c]) for c in coalitions])
在Python解释器中:
>>> agents = {"Alice": 3, "Bob": 5, "Charlie": 7, "Dave": 4}
>>> # divide sum of votes by 2, rounding up
>>> target_votes = (sum(agents.values())-1)//2+1
>>> # solve!
>>> coalitions = winning_coalitions(agents, target_votes)
>>> sorted([sorted(c) for c in coalitions])
[['Alice', 'Bob', 'Charlie'],
['Alice', 'Bob', 'Charlie', 'Dave'],
['Alice', 'Bob', 'Dave'],
['Alice', 'Charlie'],
['Alice', 'Charlie', 'Dave'],
['Bob', 'Charlie'],
['Bob', 'Charlie', 'Dave'],
['Charlie', 'Dave']]
将每个代理的投票数排列成一个数组,并从右开始计算部分和,这样您就可以通过查找部分和来找出SUM_i = k to n votes [i]。
然后对{1,2,…n}的所有可能子集进行回溯搜索。在回溯的任何一点上,您都接受了代理0..I - 1,从部分和可以知道其他代理的最大可能票数。因此,您可以查看当前子集是否可以扩展为代理数>= i以形成获胜的联盟,如果不能,则丢弃它。
这给了你一个回溯搜索,你只考虑一个子集,如果它已经是一个胜利的联盟,或者你将扩展它成为一个胜利的联盟。所以我认为回溯搜索的成本是你发现的获胜联盟规模的总和,这似乎接近于最优。我很想在运行这个之前重新安排代理,这样你就可以先处理投票最多的代理,但目前我没有看到一个论点说你从中获得了很多。
实际上——从Alf的回答中得到一个提示——如果你从完整的代理集合开始,然后使用回溯搜索来决定放弃哪些代理,生活会容易得多。这样你就不需要一个部分和的数组,你只需要生成你想要的子集。是的,没有必要提前订购代理商。
- std::unordered_map 搜索算法是如何实现的?
- C++线性搜索算法,确定数组中元素的数量
- 对于具有引用返回类型的搜索算法,默认返回值应该是什么?
- 使用迭代深度优先搜索算法的未加权图的最短路径
- 尝试实现二叉搜索算法,似乎无法使其工作
- 图上的深度优先搜索算法中的内存泄漏
- 使用图形的字符串搜索算法?C++
- 使用 while 循环和搜索算法进行复制
- C++ 循环和搜索算法,重复
- 了解一种神秘地起作用的递归二进制搜索算法
- 双二叉搜索算法
- 修改广度优先搜索算法以记住矩阵中的最短路径
- C 搜索算法第一个数字= n
- 如何在较高和较低数字的阵列中适应搜索算法(3N / 2)-2
- 需要矩阵搜索算法
- C++搜索算法-处理海量数据
- 从给定的 IPv6:端口列表中搜索 IPv6:端口组合的最快搜索算法是什么 O(1) 时间一致性
- 在两个方向上寻找搜索算法 - c / c ++ / awk
- 质数搜索算法(两种不同的算法)和Prime表的使用
- 联盟搜索算法