Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/142.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
Algorithm 来自访谈:删除n×中的行和列;n矩阵最大化剩余值之和_Algorithm_Multidimensional Array_Matrix - Fatal编程技术网

Algorithm 来自访谈:删除n×中的行和列;n矩阵最大化剩余值之和

Algorithm 来自访谈:删除n×中的行和列;n矩阵最大化剩余值之和,algorithm,multidimensional-array,matrix,Algorithm,Multidimensional Array,Matrix,给定一个实数的n×n矩阵。允许您删除任意数量(从0到n)的行和任意数量(从0到n)的列,然后计算剩余条目的总和。提出一种算法,找出要删除哪些行和列,以最大化该总和。蛮力方法是这样的: 对于n行,有2n个子集 对于n列,有2n个子集 对于nxn矩阵,有22n个子集 0元素是一个有效的子集,但很明显,如果您有0行或0列,那么总数是0,因此实际上有22n-2+1子集,但这没有什么不同 所以你可以用蛮力算出每个组合,作为一个O(an)算法。快速。:) 通过将网格中的所有正数相加,可以更快地计算出最大

给定一个实数的n×n矩阵。允许您删除任意数量(从0到n)的行和任意数量(从0到n)的列,然后计算剩余条目的总和。提出一种算法,找出要删除哪些行和列,以最大化该总和。

蛮力方法是这样的:

  • 对于n行,有2n个子集
  • 对于n列,有2n个子集
  • 对于nxn矩阵,有22n个子集
0元素是一个有效的子集,但很明显,如果您有0行或0列,那么总数是0,因此实际上有22n-2+1子集,但这没有什么不同

所以你可以用蛮力算出每个组合,作为一个O(an)算法。快速。:)

通过将网格中的所有正数相加,可以更快地计算出最大可能值。如果这些数字恰好形成了一个有效的子矩阵(这意味着您可以通过删除行和/或列来创建该集合),那么这就是您的答案

这意味着,如果没有一个数字是负数,那么根据定义,完整矩阵就是答案

另外,知道可能的最大值是多少,可以使您简化暴力评估,因为如果您得到的任何组合等于该最大值,那么这就是您的答案,您可以停止检查

另外,如果所有的数字都是非正数,那么答案就是最大值,因为根据定义,可以将矩阵缩减为1 x 1矩阵,其中包含1个值

这里有一个想法:构造2n-1nxm矩阵,其中1
  • 创建一个n×1的向量行和,以及一个n×1的向量列和。将它们初始化为原始矩阵的行和列和。O(n²)
  • 如果任何行或列的总和为负数,请删除编辑:具有最小值的行或列,并在另一个方向更新总和以反映其新值。O(n)
  • 当没有行或列的和小于零时停止
这是对另一个答案进行改进的迭代变体。它在O(n²)时间内运行,但在其他答案中提到的某些情况下失败,这是该问题的复杂性限制(矩阵中有n²个条目,甚至要找到最小值,您必须检查每个单元格一次)

编辑:以下矩阵没有负行或负列,但也没有最大化,我的算法没有捕捉到它

1     1     3        goal     1    3
1   -89   101        ===>     1  101
1   102   -99
下面的矩阵确实有负的行和列,但我的算法选择了错误的行和列进行删除

 -5     1    -5      goal     1
  1     1     1      ===>     1
-10     2   -10               2

                     mine
                     ===>     1     1     1

我真的无法在头脑中产生一个算法,但对我来说,它“闻起来”像动态规划,如果它作为一个起点的话。

问题是。(因此,你不应该期望多项式时间算法来解决这个问题。不过,仍然可能有(非多项式时间)算法比蛮力略好。)证明NP硬度背后的想法是,如果我们能够解决这个问题,那么我们就可以在一般图中解决这个问题。(最大团问题是找到图中最大的成对连通顶点集。)

具体地说,给定任何具有n个顶点的图,让我们用条目
A[i][j]
形成矩阵A,如下所示:

  • a[i][j]=1的
    i==j
    (对角线条目)
  • a[i][j]=0
    如果边(i,j)出现在图中(和
    i≠j
  • a[i][j]=-n-1
    如果边(i,j)不在图形中
现在假设我们解决了删除一些行和列(或者等价地,保留一些行和列)的问题,这样矩阵中的条目之和就最大化了。然后,答案给出了图中的最大团:

  • 索赔:在任何最佳解决方案中,没有保留边(i,j)在图中不存在的行
    i
    和列
    j
    。证明:由于
    a[i][j]=-n-1
    且所有正项目的总和最多为
    n
    ,因此选择(i,j)将导致负和。(请注意,删除所有行和列将得到更好的总和,即0。)

  • 索赔:在(某些)最优解决方案中,保留的行和列的集合是相同的。这是因为从任何最佳解决方案开始,我们可以简单地删除未保留列
    i
    的所有行
    i
    ,反之亦然。请注意,由于唯一的正条目是对角线条目,因此我们不会减少总和(根据之前的声明,我们也不会增加总和)


  • 所有这些都意味着,如果图有一个最大团大小
    k
    ,那么我们的矩阵问题有一个和
    k
    的解,反之亦然。因此,如果我们能在多项式时间内解决初始问题,那么集团问题也会在多项式时间内得到解决。这证明了最初的问题是。(实际上,很容易看出,初始问题的决策版本——是否有一种方法可以删除某些行和列,从而使总和至少为
    k
    ——是NP,因此(初始问题的决策版本)实际上是NP。)

    以一种简单的方式进行尝试:

    我们需要项集{A00,A01,A02,…,A0n,A10,…,Ann}的有效子集,其最大和

    首先计算所有子集(幂集)

    有效子集是幂集的成员,对于每两个包含的条目Aij和A(i+x)(j+y),它还包含元素A(i+x)j和Ai(j+y)(它们是由Aij和A(i+x)(j+y)跨越的矩形的剩余角)

    这样,您就可以从幂集中删除无效的幂,并找到剩余幂和最大的幂

    我相信它可以通过改进幂集的算法来改进
    Aij ...
     .       .   
     .       .
        ... A(i+x)(j+y)     
    
    def maximize_sum(m):
      frontier = [(m, 0, False)]
      best = None
      best_score = 0
    
      while frontier:
        current, startidx, cols_done = frontier.pop()
        score = matrix_sum(current)
        if score > best_score or not best:
          best = current
          best_score = score
        w, h = matrix_size(current)
        if not cols_done:
          for x in range(startidx, w):
            frontier.append((delete_column(current, x), x, False))
          startidx = 0
        for y in range(startidx, h):
          frontier.append((delete_row(current, y), y, True))
      return best_score, best
    
    >>> m = ((1, 1, 3), (1, -89, 101), (1, 102, -99))
    >>> maximize_sum(m)
    (106, [(1, 3), (1, 101)])
    
    -1  1  0           1  1  1
    -4  1 -4           5  7 1
     1  2  4    ===>  
     5  7  1  
    
    2    1
    
    3    -10
    
    Cost to take row      Cost to take column
           3                      5
    
          -7                      -9
    
    function pruneMatrix(matrix) {
      max = -inf;
      bestRowBitField = null;
      bestColBitField = null;
      for(rowBitField=0; rowBitField<2^matrix.height; rowBitField++) {
        for (colBitField=0; colBitField<2^matrix.width; colBitField++) {
          sum = calcSum(matrix, rowBitField, colBitField);
          if (sum > max) {
            max = sum;
            bestRowBitField = rowBitField;
            bestColBitField = colBitField;
          }
        }
      }
      return removeFieldsFromMatrix(bestRowBitField, bestColBitField);
    }
    
    function calcSumForCombination(matrix, rowBitField, colBitField) {
      sum = 0;
      for(i=0; i<matrix.height; i++) {
        for(j=0; j<matrix.width; j++) {
          if (rowBitField & 1<<i && colBitField & 1<<j) {
            sum += matrix[i][j];
          }
        }
      }
      return sum;
    }