【问题标题】:Algorithm for polygon with weight on vertices and operations on edges具有顶点权重和边缘操作的多边形算法
【发布时间】:2013-01-02 08:10:15
【问题描述】:

我正在考虑以下问题的算法(在 carrercup 上找到):

给定一个具有 N 个顶点和 N 个边的多边形。每个顶点上都有一个 int 数(可能是负数),每条边上都有一个 set(*,+) 中的操作。每次,我们从多边形中删除一条边 E,将由边(V1,V2)链接的两个顶点合并为一个新顶点,其值为:V1 op(E) V2。最后一种情况是两个顶点有两条边,结果是更大的一个。 返回可以从给定多边形中获取的最大结果值。

我认为我们可以只使用贪婪的方法。 IE。对于具有 k 个边的多边形,找到一对 (p, q),它在折叠时产生最大数量: (p ,q) = max ({i operation j : i, j - 相邻边)

然后只调用多边形的递归: 1. 让函数 CollapseMaxPair( P(k) ) - 获取具有 k 个边的多边形并返回具有 k-1 个边的“折叠”多边形 2.然后我们的递归:

 P = P(N);
 Releat until two edges left
     P =  CollapseMaxPair( P )
 maxvalue = max ( two remained values)

你怎么看?

【问题讨论】:

    标签: algorithm language-agnostic polygon


    【解决方案1】:

    我认为贪心算法行不通。设顶点为 A = 0, B = 1, C = 2,边为 AB = a - 5b, BC = b + c, CA = -20。贪心算法首先选择 BC 进行评估,值 3。然后选择 AB,值,-15。但是,有一个更好的顺序可以使用。首先评估 AB,值为 -5。然后评估 BC,值为 -3。不过我不知道有更好的算法。

    【讨论】:

    • AB = a - 5b, BC = b + c, CA = -20 是什么意思?边没有任何权重。如果你有 A = 0、B = 1、C = 2 和边 AB = AC = BC = {+},那么我的方法给你 A = 0,B' = 折叠的 BC = 3,我们得到它。还是我错过了什么?
    • 哦,我误解了你的问题。我认为边缘是仅使用 + 和 * 的函数。所以它只有一个 + 或 *?
    • 是的,它只是一个操作,而不是一个函数。
    【解决方案2】:

    这是你的贪心算法失败的情况:

    假设您的多边形是一个具有顶点 A、B、C、D(左上、右上、右下、左下)的正方形。这给了我们边 (A,B)、(A,D)、(B,C) 和 (C, D)。

    让权重为 A=-1、B=-1、C=-1 和 D=1,000,000。

    A (-1) ------ B (-1)  
    |             |  
    |             |  
    |             |  
    |             |  
    D(1000000) ---C (-1)  
    

    显然,最好的策略是先折叠 (A,B),然后再折叠 (B,C),这样您最终可能会得到 D。但是,您的算法将从 (A,D) 或 (D,C) 开始,这不是最优的。

    结合最小和的贪心算法也有类似的弱点,因此我们需要考虑其他方法。

    我开始了解我们希望如何尝试将所有正数放在一边,而将所有负数放在另一边。

    如果我们将初始多边形完全视为一个状态,那么我们可以将所有可能的子状态想象为随后的图,即边折叠。这将创建一个树状结构。 BFS 或 DFS 最终会给我们一个最佳解决方案,但代价是在最坏的情况下遍历整个树,这可能没有您想要的效率。

    您正在寻找的是一种贪婪的最佳优先方法来搜索这棵可证明是最优的树。也许您可以通过它创建类似 A* 的搜索,尽管我不确定您可接受的启发式方法是什么。

    【讨论】:

    • 真的很有趣!我正在考虑一些 DP 解决方案(类似于“最大化括号”),但无法提出解决方案。
    • 我认为在这种情况下动态编程将是一个非常好的主意!
    【解决方案3】:

    我在这里回答了这个问题:Google Interview : Find the maximum sum of a polygon,有人向我指出这个问题与这个问题重复。由于尚未完全回答此问题,因此我决定在此处也添加此答案。

    正如您正确识别(标记)的那样,这确实与矩阵乘法问题非常相似(我以什么顺序将矩阵相乘以便快速完成)。

    这可以使用动态算法以多项式方式求解。

    我将改为解决一个类似的、更经典的(和相同的)问题,给定一个包含数字、加法和乘法的公式,例如,用什么括号括起来会给出最大值 6+1 * 2 变为 (6+1)*2 大于 6+(1*2)

    让我们用*+ 表示我们的输入a1 to an 实数和o(1),...o(n-1)。我们的方法将按如下方式工作,我们将观察子问题 F(i,j),它表示 a1,...aj 的最大公式(在括号化之后)。我们将创建一个包含此类子问题的表,并观察 F(1,n) 正是我们正在寻找的结果。

    定义

    F(i,j)
    
     - If i>j return 0 //no sub-formula of negative length
     - If i=j return ai // the maximal formula for one number is the number
     - If i<j return the maximal value for all m between i (including) and j (not included) of:
         F(i,m) (o(m)) F(m+1,j) //check all places for possible parenthasis insertion
    

    这会遍历所有可能的选项。正确性的证明是通过对大小 n=j-i 的归纳来完成的,而且非常简单。

    让我们进行运行时分析:

    如果我们不为较小的子问题动态保存值,这会运行得很慢,但是我们可以让这个算法在 O(n^3) 中执行得相对较快

    我们创建一个 *n 表 T,其中索引 i,j 处的单元格包含 F(i,j) 填充 F(i,i) 和 F(i,j) 对于小于 i 的 j 在 O( 1) 对于每个单元格,因为我们可以直接计算这些值,所以我们对角线填充 F(i+1,i+1) (我们可以快速完成,因为我们已经知道递归公式中的所有先前值),我们对 n 条对角线重复此操作 n 次(实际上是表中的所有对角线)并填充每个单元格需要 (O(n)),因为每个单元格有 O(n) 个单元格,我们在 O(n^2) 中填充每个对角线意味着我们在 O(n^3) 中填写所有表格。填写表格后,我们显然知道 F(1,n) 是您问题的解决方案。

    现在回到你的问题

    如果您将多边形转换为 n 不同的公式(一个用于从每个顶点开始)并在其上运行公式值的算法,您将得到您想要的值。

    【讨论】:

    • 我认为 OP 的问题与您解决的问题不同。如果给定一个数组,则不能对 a[0]a[n-1] 进行操作,但它对多边形的顶点有效。
    猜你喜欢
    • 2010-10-03
    • 2011-09-15
    • 2018-04-10
    • 1970-01-01
    • 2015-03-26
    • 2013-05-21
    • 2019-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多