簡體   English   中英

2D數組:2d數組的子方格元素的總和

[英]2D array: Sum of elements of a subsquare of the 2d array

給定一個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];
 }
}

我相信從一個[0] [0]開始,它總計一個3x3的單元格。 我迷失了如何從這里獲得所有其他3x3細胞組合並比較它們以找到最低的3x3細胞值。 如果我可以使用下一個3x3單元格,我知道我可以使用某種比較語句,並將sum變量更改為下一個總和(如果它更低)。

我怎么能做到這一點? 我是否需要在for循環中添加更多圖層?

讓我們從定義開始:

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

你所寫的代碼,兩個for循環停止在3,可以計算你想要的3x3子矩陣中從[0] [0]開始的數字,正如你所說的那樣。 你現在需要做的是:

  1. 確定您擁有的所有起點,確保其中包含3行和3列,包括您所在的元素,並根據每個可能的起點調用該函數,並且

  2. 擴展該代碼,使其可以從矩陣中的任何點開始。

以下是我們如何進行第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子矩陣? 首先,你可以找到所有3個“垂直”組,即N-3 + 1。 對於他們每個人,你能形成多少“水平”的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;
}

應該這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM