优化问题 - 找到最大值

时间:2010-07-21 18:43:04

标签: algorithm optimization discrete-mathematics

我手边有一个问题,可以简化为:

假设在二维平面X-Y中有一堆随机点,对于每个Y,X上可能有多个点,对于每个X,Y上可能有多个点。

每当选择一个点(Xi,Yi)时,不能选择X = Xi OR Y = Yi的其他点。我们必须选择最大点数。

7 个答案:

答案 0 :(得分:11)

这可以简化为简单的最大流量问题。如果你有一个点(xi,yi),在图中它应该用从源S到点xi的路径表示,从xi到yi,从yi到最后一个节点(sink)T。

注意,如果我们有点(2,2)和(2,5),那么从S到x2的路径仍然只有一条。所有路径(边)都具有容量1.

此网络中的流程就是答案。

关于一般问题
http://en.wikipedia.org/wiki/Max_flow

<强>更新
我现在没有图形编辑器可视化问题,但您可以轻松地手动绘制示例。比方说,积分是(3,3)(3,5)(2,5)

然后边(路径)将是
S - &gt; x2,S - &gt; X3
y3 - &gt; T,y5 - &gt; Ť
x3 - &gt; y3,x3 - &gt; y5,x2 - &gt; Y5

流程:S - &gt; x2 - &gt; y5 - &gt; T和S - &gt; x3 - &gt; y3 - &gt; Ť
从源到汇的“水”量是2,答案也是如此。

还有一个关于最大流量算法的教程 http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=maxFlow

答案 1 :(得分:3)

这不仅仅是Hungarian algorithm吗?

创建 n×n 矩阵,在标记的顶点处为0,在未标记的顶点处为1。算法将选择 n 顶点,每个行和每一个顶点,最小化它们的总和。只需计算所有等于0的所选顶点,就可以得到答案。

from munkres import Munkres

matrix = [[0, 0, 1],
          [0, 1, 1],
          [1, 0, 0]]

m = Munkres()
total = 0
for row, column in m.compute(matrix):
    if matrix[row][column] == 0:
        print '(%i, %i)' % (row, column)
        total += 1

print 'Total: %i' % total

这在O(n 3 )时间运行,其中 n 是矩阵中的行数。最大流量解在O(V 3 )中运行,其中 V 是顶点数。只要有超过 n 选择的交叉点,这就会更快;实际上,随着所选顶点的数量增加,它的运行速度会快一些。

答案 2 :(得分:1)

不同的解决方案。事实证明,存在很多对称性,答案比我原先想象的要简单得多。您可以做的最大事情是唯一X和唯一Y的最小值,如果您只想要结果,则为O(NlogN)。

每个其他形状相当于一个包含点的矩形,因为从矩形中心拉出的点数无关紧要,顺序永远不会重要(如果处理如下)。 你从现在开始点的任何形状都有一个不那么独特的X和一个不那么独特的Y,就像一个矩形。

因此,最佳解决方案与连通性无关。选择位于最小维度边缘的任何点(即,如果len(unique-Xs)&gt; len(unique-Ys),则选择具有最大或最小X的任何内容)。它有多少连接并不重要,只有哪个维度最大,这可以在查看上面创建的排序唯一列表时轻松完成。如果保留unique-x和unique-y计数器并在删除列表中该元素中的所有唯一节点时递减它们,则每次删除都为O(1)并重新计算长度为O(1)。所以重复N次是最坏的O(N),最后的复杂性是O(NlogN)(仅归因于排序)。

您可以在最短的边缘选择任意点,因为:

  • 如果只有一个在这个边缘,你最好现在选择它或其他东西将消除它
  • 如果在这个边缘有多个,谁在乎,你将用你的选择消除所有这些

基本上,你在每个点上最大化“max(uniqX,uniqY)”。

更新:IVlad抓住了一个边缘案例:

如果尺寸相等,则采用最少点的边缘。即使它们不相等,也要从你所消除的唯一堆栈的顶部或底部取得最少的点。

案例:

转1:

  • 积分:(1, 2); (3, 5); (10, 5); (10, 2); (10, 3)
  • 有3个独特的X:1, 3, 10
  • 有3个独特的Y:2, 3, 5
  • “边界框”为(1,5),(10,5),(10,2),(1,2)

反应1:

  • 点数最少的“外边缘”(最外面的uniqueX或唯一Y点列表)是左边。基本上,看看x = 1,x = 10和y = 2,y = 5的点集。 x = 1的集合是最小的:一个点。选择x = 1的唯一点 - &gt; (1,2)
  • 这也消除了(10,2)

转2:

  • 积分:(3, 5); (10, 5); (10, 3)
  • 有两个独特的X:3, 10
  • 有两个独特的Y:3, 5
  • “边界框”为(3,5),(10,5),(10,3),(3,3)

反应2:

  • 具有最小值的边界框的“边缘”是底部或左边。我们达到了琐碎的情况 - 4个点意味着所有边缘都是外边缘。消除一个。说(10,3)
  • 这也消除了(10,5)

转3:

  • 积分:(3, 5)

反应3:

  • 删除(3,5)

答案 3 :(得分:0)

对于每个点,确定通过选择该点而被取消资格的其他点(N)的数量(即具有相同X或Y值的那些点)。然后,按照N个不合格点数量的增加顺序迭代非取消资格的点。完成后,您将删除最大分数。

答案 4 :(得分:0)

这看起来像dynamic programming可以解决的问题。查看最长公共子字符串的算法,或knapsack problem

答案 5 :(得分:0)

XY平面是红鲱鱼。将其短语作为一组元素,每个元素都有一组互斥的元素。

然后算法成为深度优先搜索。在每个级别,对于每个候选节点,计算排除元素的集合,当前排除元素与候选节点排除的元素的并集。按最少排除元素的顺序尝试候选节点。跟踪目前为止的最佳解决方案(排除最少的节点)。修剪任何比当前最差的子树。

作为可能遗漏解决方案成本的略微改进,您可以使用Bloom过滤器来跟踪排除的集合。

答案 6 :(得分:-1)