Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 在二维数组中查找所有可能的行和_Arrays_Algorithm_Performance_Optimization_Math - Fatal编程技术网

Arrays 在二维数组中查找所有可能的行和

Arrays 在二维数组中查找所有可能的行和,arrays,algorithm,performance,optimization,math,Arrays,Algorithm,Performance,Optimization,Math,理想情况下,我正在寻找一个c#解决方案,但算法上的任何帮助都可以 我有一个二维数组(x,y)。最大列数(max x)在2到10之间变化,但可以在实际填充阵列之前确定。最大行数(y)固定为5,但每列可以有不同数量的值,例如: 1 2 3 4 5 6 7...10 A 1 1 7 9 1 1 B 2 2 5 2 2 C 3 3 D 4 E 5 我需要计算出所有可能的行数总和,以便找到一个具体的总和。也就是说,行总计可

理想情况下,我正在寻找一个c#解决方案,但算法上的任何帮助都可以

我有一个二维数组(x,y)。最大列数(max x)在2到10之间变化,但可以在实际填充阵列之前确定。最大行数(y)固定为5,但每列可以有不同数量的值,例如:

   1 2 3 4 5 6 7...10

A  1 1 7   9 1 1
B  2 2 5   2 2
C  3         3
D            4
E            5
我需要计算出所有可能的行数总和,以便找到一个具体的总和。也就是说,行总计可以是单元格A1+B2+A3+B5+D6+A7(每列中一个值的任意组合)

这个过程将重复数百次,每次使用不同的单元格值,因此我正在寻找一个稍微优雅的解决方案(比我能够提供的更好)。谢谢您的帮助。

问题的大小 我们首先考虑最坏的情况:

每列有10列和5(完整)行。应该清楚的是,你将能够得到(每个地方有适当数量的人口)最多5^10≅ 10^6不同的结果(解决方案空间)

例如,以下矩阵将给出3列的最坏情况:

| 1  10  100 |
| 2  20  200 |
| 3  30  300 |
| 4  40  400 |
| 5  50  500 |
导致5^3=125个不同的结果。每个结果的形式为{a1 a2 a3}和ai∈ {1,5}

很容易证明这样一个矩阵对于任意数量的n列总是存在的

现在,为了得到每一个数值结果,你需要做n-1个和,把问题的大小加起来就是O(n5^n)。所以,这是最糟糕的情况,我认为对此无能为力,因为要知道可能的结果,你需要有效地执行求和

更温和的化身:

可以通过两种方式消除问题的复杂性:

  • 更少的数字(即并非所有列都已满)
  • 重复的结果(即多个部分和给出相同的结果,您可以将它们合并到一个线程中)。稍后将介绍更多内容 让我们看一个简化后的示例,其中有两行:

    | 7  6  100 |
    | 3  4  200 |
    | 1  2  200 |
    
    乍一看,你需要做23^3和。但事实并非如此。当您将第一列相加时,您不会得到预期的9个不同结果,而只有6个({13,11,9,7,5,3})。
    所以你不必把你的九个结果带到第三列,只需要6个

    当然,这是以从列表中删除重复编号为代价的。“删除重复的整数元素”,我不在这里重复讨论,只引用在列表大小(m)中执行mergesort O(m log m)将删除重复项。如果您想要更简单的东西,可以使用双循环O(m^2)

    无论如何,出于几个原因,我不会用这种方法计算(平均)问题的大小。其中之一是排序合并中的“m”不是问题的大小,而是将任意两列相加后结果向量的大小,并且该操作重复(n-1)次。。。我真的不想做数学:(。 另一个原因是,当我实现该算法时,我们将能够使用一些实验结果,从而避免我的理论考虑

    算法 根据我们之前所说的,显然我们应该针对良性病例进行优化,因为最坏的病例是丢失的。
    为此,我们需要对列使用列表(或变量dim向量,或任何可以模拟这些的东西),并在每个列添加后进行合并。
    在不修改结果的情况下,可以用其他几种算法(例如在BTree上插入)替换合并

    因此,算法(过程伪代码)类似于:

     Set result_vector to Column 1
     For column i in (2 to n-1)
        Remove repeated integers in the result_vector
        Add every element of result_vector to every element of column i+1
               giving a new result vector
     Next column
     Remove repeated integers in the result_vector
    
    或者,按照您的要求,递归版本的工作方式如下:

    function genResVector(a:list, b:list): returns list  
                      local c:list  
                      {  
                       Set c = CartesianProduct (a x b)  
                       Set c = Sum up each element {a[i],b[j]} of c  </code>
                       Drop repeated elements of c
                       Return(c)
                      }
    
    function ResursiveAdd(a:matrix, i integer): returns list
                      {
                       genResVector[Column i from a, RecursiveAdd[a, i-1]]; 
                      }
    function ResursiveAdd(a:matrix, i==0 integer): returns list={0}
    
    算法实现(递归) 我选择函数式语言,我想把它翻译成任何过程式语言都没什么大不了的

    我们的程序有两个功能:

  • genResVector,它对两个列表求和,给出所有可能的结果,并删除重复的元素,以及
  • recursiveAdd,它在矩阵列上递归,将所有列相加
  • recursiveAdd,它在矩阵列上递归,将所有列相加

    代码是:

     genResVector[x__, y__] :=  (* Header: A function that takes two lists as input *)
    
          Union[        (* remove duplicates from resulting list *)
    
            Apply       (* distribute the following function on the lists *)
    
                [Plus,  (* "Add" is the function to be distributed *)
    
                  Tuples[{x, y}],2] (*generate all combinations of the two lists *)];
    
    
     recursiveAdd[t_, i_] := genResVector[t[[i]], recursiveAdd[t, i - 1]]; 
                                           (* Recursive add function *)
     recursiveAdd[t_, 0] := {0};           (* With its stop pit      *)
    
    试验

    如果我们以你的清单为例

    | 1 1 7 9 1 1 |  
    | 2 2 5 2 2   |  
    | 3       3   |  
    |         4   |  
    |         5   |  
    
    然后运行程序,结果是:

    {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}
    
    最大值和最小值很容易验证,因为它们对应于从每个列中获取最小值或最大值

    一些有趣的结果

    让我们考虑当矩阵的每个位置上的数有界时会发生什么。对于这个,我们将取一个完整的(10×5)矩阵,并用随机整数填充它。 在整数仅为0或1的极端情况下,我们可以预期两件事:

  • 非常小的结果集
  • 快速执行,因为会有大量重复的中间结果
  • 如果我们增加随机整数的范围,我们可能期望增加结果集和执行时间


    实验1:5x10矩阵填充不同范围的随机整数

    很明显,对于接近最大结果集大小(5^10)的结果集≅ 10^6)计算时间和“结果数”有一个渐近线。我们看到函数增加的事实表明我们离那个点还很远

    士气:你的元素越小,你越有可能快速获得它。这是因为你可能有很多重复

    请注意,对于测试的最坏情况,我们的最大计算时间接近20秒


    实验2:不可用的优化

    有了大量可用的内存,我们可以用蛮力计算,而不需要删除重复的结果

    结果很有趣…10.6秒!…等等!发生了什么事?我们的“删除重复整数”小把戏占用了很多时间,当没有太多的结果要删除时,没有任何好处,但在尝试消除重复时会有所松动

    但我们可能会得到很多好处