在矩阵中找到连通单元的最有效方法

时间:2016-05-10 12:04:01

标签: arrays algorithm matrix

我有一个带有数值的矩阵(最大尺寸为100 x 100),需要找到总计达到所需值的连接单元的最有效(最小单元格数)组。该矩阵也可以具有负单元(矩阵的内壁),该算法应该能够四处走动。在查找连接的单元时,我不需要考虑对角线单元(仅向上,向下,向左,向右)。

例如,我们有以下矩阵:

1 4 4

1 1 2

4 -1 1

如果我们正在寻找总结为:

的细胞集
  • 9正确的结果是:4(0x2),4(0x1),1(0x0或1x1)
  • 3正确的结果是:2(1x2),1(1x1或2x2)
  • 5正确的结果是:4(0x1),1(0x0或1x1)

找到这些连接的单元格的最有效方法是什么,因为递归将在矩阵变得相对较大(如50x50)时非常慢?或者这些数据的矩阵表示不是此任务的最佳方式?

由于

2 个答案:

答案 0 :(得分:2)

NP-硬度

正如评论中sascha所建议的,这个问题是NP难的,因此不太可能存在有效的(多项式时间)解决方案。这是Subset Sum问题的减少,我们给出了一个目标值m和一个多个n个数字的集合,并询问是否有可能找到这些n个数的子数据总和为m:

  1. 以任意顺序创建一个矩阵行,其中包含子集总和问题的所有n个值。
  2. 在其下方创建第二个矩阵行,每个单元格中包含值0。
  3. 使用m作为目标值,在结果矩阵上解决问题。
  4. 现在任何解决方案都可以获取整个0行的值,然后在顶行中选择任何子集,因为它们都连接到第二行。因此,如果子集总和问题有解决方案,那么您的问题就有了相应的解决方案,反之亦然。

    子集和是一个NP难问题,上面显示了一种解决任意子集和问题的方法,将其转化为问题的实例然后解决了这个问题,所以你的问题也必须是NP难的

    如果只能选择正数

    我在上面假设零值可以出现在矩阵中(并且可以被选中)。如果OTOH只能选择正数,则可以调整减少量:

    设z比子集和问题的所有n个输入数的绝对值之和多一个。而不是单行0值,而是创建一行z值;而不是将m作为目标,取m + nz。显然,如果SS问题有解决方案,那么我们可以通过选择SS解决方案选择的顶行中的特定数字以及底行的z值的所有n个副本来解决我们的问题。 。我现在表明另一个方向也是有效的:也就是说,如果我们可以在构造的问题实例中获得m + nz的目标,那么它必须在底行使用z值的所有n个副本,在顶行中留下总共m,对应于原始SS实例的解。

    假设我们对构造的实例有一个解决方案,它击中了m + nz的目标。然后底行中的每个单元格必须是此解决方案的一部分,因为如果即使一个这样的单元格不是,那么即使我们包括,我们也无法达到nz的总和(更不用说可能更大的值m + nz) 顶行中的每个元素,因为(按设计)z> sum(顶行中的所有元素)。 (我假设m在这里是正面的。)

答案 1 :(得分:2)

为了尝试将递归次数减少到最小,我尝试使用此方法,该方法查找从短到长累加到目标的单元格序列,以便您首先找到最短的解决方案:

给定目标,例如10和矩阵,例如

[1, 0, 1, 2, 3]
[6, 1, 4, 0, 2]
[1, 2, 4,-2, 3]
[1,-1, 2, 3, 1]
[0, 2, 3, 0, 1]
  • 计算矩阵中每个正值的出现次数:
1: 6, 2: 5, 3: 4, 4: 2, 5: 0, 6: 1
  • 使用可用值查找目标的所有分区:
6,4  
6,3,1
6,2,2
6,2,1,1
6,1,1,1,1
4,4,2
4,4,1,1
4,3,3
4,3,2,1
4,3,1,1,1
4,2,2,2
4,2,2,1,1
4,2,1,1,1,1
4,1,1,1,1,1,1
3,3,3,1
3,3,2,2
3,3,2,1,1
3,3,1,1,1,1
3,2,2,2,1
3,2,2,1,1,1
3,2,1,1,1,1,1
2,2,2,2,2
2,2,2,2,1,1
2,2,2,1,1,1,1
2,2,1,1,1,1,1,1

(由于目标非常小,分区的数量不应该很大。如果目标是20,则最大分区数仅为627。)

  • 将分区从短到长排序:
6,4  
6,3,1
6,2,2
4,4,2
4,3,3
6,2,1,1
...
  • 从最短的分区开始,尝试在矩阵中找到它:
    • 找到最大数字的位置,将单元格标记为选区中包含的单元格,并与分区的其余部分一起递归。
    • 尝试使用分区中的相邻数字来增加选择。
    • 如果找不到完整的分区,请跳至下一个分区。

如果矩阵中有零可以包含在选择中,则每当分区长度增加时(例如,当您从4,3,3移动到6,2,1,1时,重试用零填充的较短分区(如果可以的话)。

如果矩阵中的值非常随机,即没有专门设计使其难以找到解,那么我认为这种方法应该大大减少必要的递归次数。 (我还没有试过编码,所以我无法做出很好的估计。)