2D数组:2d数组的子方格元素的总和

时间:2015-02-14 00:13:05

标签: c++ arrays comparison 2d

给定一个2D数组,我可以毫不费力地将所有元素添加到sum变量中。说一个4x4阵列:

  

1 2 3 4

     

1 2 2 3

     

1 2 2 2

     

1 1 3 3

我总结其所有元素的代码是做一个for循环:

for (i = 0; i < rows; i++)
{
 for (j = 0; j < columns; j++)
 {
   sum += somearray[i][j];
 }
}  

我认为这是正确的,假设所有变量都被正确声明了。但是,我无法在同一个数组中对3x3单元格求和。我想找到产生最低总和的3x3单元格。

for (i = 0; i < 3; i++)
{
 for (j = 0; j < 3; j+++
 {
   sum += somearray[i][j];
 }
}

我认为这可以从aarray [0] [0]开始计算一个3x3的单元格。我迷失了如何从这里获得所有其他3x3细胞组合并比较它们以找到最低的3x3细胞值。如果我可以使用下一个3x3单元格,我知道我可以使用某种比较语句,并将sum变量更改为下一个总和(如果它更低)。

我怎样才能做到这一点?我是否需要在for循环中添加更多图层?

2 个答案:

答案 0 :(得分:0)

让我们从定义开始:

size_t rows; // number of rows
size_t columns; // number of columns
int array[rows][columns];

辅助功能:

int sum(size_t row, size_t column)
{
   int res = 0;

   if (row > rows - 3 || column > columns - 3)
   {
      abort(); // we can out of index operations here...
   }

   for (size_t i = 0; i < 3; ++i)
   {
       for (size_t j = 0; j < 3; ++j)
       {
           res += array[i + row][j + column];
       }
   }
   return res;
}

现在我们可以开始......

int min_value = INT_MAX;  // Just the maximum we can imaging
size_t min_row = 0, min_column = 0; // whatever

for (size_t i = 0; i <= rows - 3; ++i)
{
   for (size_t j = 0; j <= columns - 3; ++j)
   {
      int value = sum(i, j);
      if (value < min_value)
      {
         min_value = value;
         min_row = i;
         min_column = j;
      }
   }
}
... // done - here min_value is the minimum sum,
    // and min_row, min_column are indexes of the 3x3 entry

答案 1 :(得分:0)

你所写的代码,两个for循环停止在3,可以计算你想要的3x3子矩阵中从[0] [0]开始的数字,正如你所说的那样。你现在需要做的是:

  1. 确定您拥有的所有起点,确保这一点 那里有3行3列,包括 您所在的元素,并且每个可能的函数调用一次函数 起点,

  2. 扩展该代码,使其可以从中的任何一点开始 基质

  3. 以下是我们如何进行第1点:

    你有一个4x4矩阵,但我们可以很容易地将它推广到NxM矩阵。 N表示有N行,即每列有N个元素。所以让我们考虑一个专栏。如果你有N个元素,你可以找到3个连续元素的组?注意,它不是N-3(这看起来很明显,但它错了):

    • N = 3个元素,它只有1个(如果你有123个,那么这个组是123个)
    • N = 4个元素有2个(如果有1234个,则组为123和234个)
    • N = 5个元素有3个(如果有12345个,则为123个, 234,345)

    所以一般来说你有N - 3 + 1组(当然你可以认为它是N-2,但我更喜欢表达3,因为这是我们每次都要服用的元素数量)

    同样的方法可以应用于列:如果它们是M,你可以使用M - 3 + 1组。

    那就是说,你能在NxM矩阵中找到多少个3x3子矩阵?首先,你可以找到所有&#34;垂直&#34; 3组,即N-3 + 1。对于他们每个人,有多少&#34;水平&#34;你可以形成3组? M-3 + 1。然后你有总共(N-3 + 1)*(M-3 + 1)3x3子矩阵。这是检查每个子矩阵时必须进行的迭代次数。这些N-3 + 1元素中的每一个都是一行(我们是垂直移动的,也就是说,沿着一列,所以这些是行),所以这是一个我们可以开始检查矩阵的元素 - 只要我们有足够的水平空间,即有足够的列。对于每一行,我们必须检查M-3 + 1列(沿着一行水平移动),其中3x3子矩阵可以开始。

    int min_found = 0; // So far we haven't found a minimum yet
    int min_value, min_row, min_column;
    int max_rows    = (N-3+1);
    int max_columns = (M-3+1);
    
    for (int start_row = 0; start_row < max_rows; start_row++) {
        for (int start_column = 0; start_column < max_columns; start_column++) {
            int current_sum = calculate_sum_of_submatrix(start_row, start_column);
            if ( (min_found == 0) || (min_found == 1 && current_sum < min_value) ) 
                min_value = current_sum;
                min_row    = start_row;
                min_column = start_column;
                min_found = 1;
            }
        }
    }
    
    cout << "The 3x3 submatrix whose elements have the minimum sum "
         << "starts at row " << min_row << " and column " << min_column
         << ", and the sum is " << min_sum << endl;
    

    在你的情况下(N = 4,M = 4),我们将检查N-3 + 1 = 2行,并且M-3 + 1 = 2列。所以我们从[0] [0]开始,然后内部循环将我们带到[0] [1],然后内部循环将完成,我们将继续到外部循环,这将把我们带到第1行,内循环将检查[1] [0]和[1] [1]。然后就结束了。到这时我们将检查所有4个3x3子矩阵,我们知道最小值。

    现在,第2点:我们必须调整你已经拥有的功能,这样它不是始终从[0] [0]开始,而是从我们想要的地方开始。这很简单,我们只需要在起始位置(在代码中始终为[0] [0])和[i] [j]索引之和的位置读取矩阵你已经拥有了。像这样:

    int calculate_sum_of_submatrix(int start_row, int start_column) {
        int sum = 0;
        for (int i = 0; i < 3; i++) {     // I would replace i with "submatrix_row"
            for (int j = 0; j < 3; j++) { // I would replace j with "submatrix_column"
                sum += somearray[start_row + i][start_column + j];
            }
        }
        return sum;
    }
    

    应该这样做。