找到矩阵中M个相邻元素的最大和的最快方法是什么

Whats the fastest way to find biggest sum of M adjacent elements in a matrix

本文关键字:和的 是什么 方法 元素      更新时间:2023-10-16

假设我有一个维数为N(N<=50)的方阵,并且相邻元素不包括对角线。

给定M,如何找到M个相邻元素之间的最大和?

例如,以矩阵4x4:为例

Matrix:           For M = 3           For M = 4
3 1 5 2           3  1  5  2          3  1  5 2
2 6 1 3           2 [6] 1  3          2 [6] 1 3
1 4 4 2           1 [4][4] 2          1 [4] 4 2
5 3 2 7           5  3  2  7         [5][3] 2 7
                  Biggest = 14        Biggest = 18

我试着这样做,但在一定的维度之后,它非常慢。

#include <bits/stdc++.h>
using namespace std;
int mat[51][51];
int mark[51][51];
int m, n;
int biggest;
void search(int row, int column, int sum, int steps){
    if(row < 0 || row >= n || column < 0 || column >= n || mark[row][column]) {
        return;
    }
    sum += mat[row][column];
    mark[row][column] = 1;
    if(steps == m){
        if(biggest < sum) biggest = sum;
    }
    else{
        search(row - 1, column, sum, steps+1);
        search(row + 1, column, sum, steps+1);
        search(row, column + 1, sum, steps+1);
        search(row, column - 1, sum, steps+1);
    }
    mark[row][column] = 0;
}

int main(){
    memset(mat, 0, sizeof(mat));
    memset(mark, 0, sizeof(mark));
    biggest = 0;
    scanf("%d", &n);
    scanf("%d", &m);
    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            scanf("%d", &mat[i][j]);
        }
    }

    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            search(i, j, 0, 1);
        }
    }

    printf("%d", biggest);
    return 0;
}

这个答案(还)不包括代码,稍后将通过所述算法的实现进行扩展

主要的困难是某些"形状"要经过多次处理。考虑一个填充矩形的选择。它可以从任何单元格开始,以多种不同的方式("递归路径")遍历,以达到相同的选择(显然也是相同的计算)。正是这个问题需要解决。

为此,您需要预先计算可以为给定M选择的各种形状,然后迭代矩阵,并为每个单元格(用作形状的左上角)计算和比较所有形状选择的总和。

预计算是通过使用递归函数来完成的,就像在"绘制"一个(2M-1)2矩阵的问题中一样,该矩阵包含路径中的单元格,从在中间开始。在结束条件下(选择M个单元格),生成的形状将与累积的"形状列表"中的现有形状进行比较,并且只有在不存在时才添加 需要解决"+"形状场景

优化应在预计算阶段使用,以避免将问题从计算"转移"到非常大的Ms的预计算阶段,例如,限制遍历,使其超过起始行是非法的(因此,形状矩阵只需要M(2M-1)big)。

这是Python中的一个基本深度优先搜索,使用集合来散列形状(这是对我这里的答案的修订,矩阵的k个连接元素的最大和)。在我看来,DFS应该将堆栈大小保持在O(m)的数量级(尽管搜索空间仍然很大)。

from sets import Set
def f(a,m):
  stack = []
  hash = Set([])
  best = (0,[]) # sum, shape
  n = len(a)
  for y in range(n):
    for x in range(n):
      stack.append((a[y][x],Set([(y,x)]),1))
  while len(stack) > 0:
    s,shape,l = stack.pop()
    key = str(sorted(list(shape)))
    if l == m and key not in hash:
      hash.add(key)
      if s > best[0]:
        best = (s,shape)
    elif key not in hash:
      hash.add(key)
      for (y,x) in shape:
        if y < n - 1 and (y + 1,x) not in shape:
          copy = Set(shape)
          copy.add((y + 1,x))
          stack.append((s + a[y + 1][x],copy,l + 1))
        if y > 0 and (y - 1,x) not in shape:
          copy = Set(shape)
          copy.add((y - 1,x))
          stack.append((s + a[y - 1][x],copy,l + 1))
        if x < n - 1 and (y,x + 1) not in shape:
          copy = Set(shape)
          copy.add((y,x + 1))
          stack.append((s + a[y][x + 1],copy,l + 1))
        if x > 0 and (y,x - 1) not in shape:
          copy = Set(shape)
          copy.add((y,x - 1))
          stack.append((s + a[y][x - 1],copy,l + 1))
  print best
  print len(hash)

输出:

matrix = [[3, 1, 5, 2,]           
         ,[2, 6, 1, 3,]        
         ,[1, 4, 4, 2]
         ,[5, 3, 2, 7]]
f(matrix,4) 
"""
(18, Set([(3, 1), (3, 0), (2, 1), (1, 1)]))
205 hash length
"""