Maximum Submatrix & Largest Rectangle
阿新 • • 發佈:2018-08-20
org iso oid pointers 所有 tin test www. define
相關題型
問題一(最大和子矩陣) : 有一個 m x n 的矩陣,矩陣的元素可正可負。請找出該矩陣的一個子矩陣(方塊),使得其所有元素之和在所有子矩陣中最大。(問題來源:http://acm.pku.edu.cn/JudgeOnline/problem?id=1050) 問題二( 最大 0/1 方塊) :有一個 m x n 的矩陣,元素為 0 或 1。一個子矩陣,如果它所有的元素都是 0, 或者都是 1,則稱其為一個 0-聚類 或 1-聚類,統稱聚類(Cluster)。請找出最大的聚類(元素最多的聚類)(面試題) 這兩個問題,除了都是在矩陣上操作之外,似乎沒有什麽共同之處。其實不然。事實上,它們可以用同一個思路解決。該思路來源於下面的一個問題,具體地說,就是把前兩個問題化歸成多個問題三: 問題三(和最大的段) :有 n 個有正有負的數排成一行,求某個連續的段,使得其元素之和最大。(問題來源:某面試題。事實上,這也是一道經典題目,具體參考 http://en.wikipedia.org/wiki/Maximum_subarray_problem) 問題四(最大長方形) : 有一個有 n 個項的統計直方圖,假定所有的直方條 (bar) 的寬度一樣。在所有邊與 x 軸 和 y 軸平行的長方形中,求該被該直方圖包含的面積最大的長方形。(問題來源:面試經典題目)
參考
- Maximum Submatrix & Largest Rectangle
- [leetcode]221. Maximal Square
分析:動態規劃,從左上角開始,如果當前位置為1,那麽到當前位置包含的最大正方形邊長為左/左上/上的值中的最小值加一,因為邊長是由短板控制的。
- 最大子矩陣和
最大子矩陣和問題可以類比於最大字段和問題,從一維變成二維,dp思路,在輸入的時候做一個處理,讓a[i,j]變為存放前i行j列的和,降低復雜度。狀態轉移方程為sum[k+1]=sum[k]<0?0:sum[k]+a[i,j];表示第k行i到j的和。因為a[i,j]為存放前i行j列的和,所以a[i,j]=a[k,j]-a[k,i-1];
- Maximum sum rectangle in a 2D matrix | DP-27
// Program to find maximum sum subarray in a given 2D array #include <stdio.h> #include <string.h> #include <limits.h> #define ROW 4 #define COL 5 // Implementation of Kadane's algorithm for 1D array. The function // returns the maximum sum and stores starting and ending indexes of the // maximum sum subarray at addresses pointed by start and finish pointers // respectively. int kadane(int* arr, int* start, int* finish, int n) { // initialize sum, maxSum and int sum = 0, maxSum = INT_MIN, i; // Just some initial value to check for all negative values case *finish = -1; // local variable int local_start = 0; for (i = 0; i < n; ++i) { sum += arr[i]; if (sum < 0) { sum = 0; local_start = i+1; } else if (sum > maxSum) { maxSum = sum; *start = local_start; *finish = i; } } // There is at-least one non-negative number if (*finish != -1) return maxSum; // Special Case: When all numbers in arr[] are negative maxSum = arr[0]; *start = *finish = 0; // Find the maximum element in array for (i = 1; i < n; i++) { if (arr[i] > maxSum) { maxSum = arr[i]; *start = *finish = i; } } return maxSum; } // The main function that finds maximum sum rectangle in M[][] void findMaxSum(int M[][COL]) { // Variables to store the final output int maxSum = INT_MIN, finalLeft, finalRight, finalTop, finalBottom; int left, right, i; int temp[ROW], sum, start, finish; // Set the left column for (left = 0; left < COL; ++left) { // Initialize all elements of temp as 0 memset(temp, 0, sizeof(temp)); // Set the right column for the left column set by outer loop for (right = left; right < COL; ++right) { // Calculate sum between current left and right for every row 'i' for (i = 0; i < ROW; ++i) temp[i] += M[i][right]; // Find the maximum sum subarray in temp[]. The kadane() // function also sets values of start and finish. So 'sum' is // sum of rectangle between (start, left) and (finish, right) // which is the maximum sum with boundary columns strictly as // left and right. sum = kadane(temp, &start, &finish, ROW); // Compare sum with maximum sum so far. If sum is more, then // update maxSum and other output values if (sum > maxSum) { maxSum = sum; finalLeft = left; finalRight = right; finalTop = start; finalBottom = finish; } } } // Print final values printf("(Top, Left) (%d, %d)\n", finalTop, finalLeft); printf("(Bottom, Right) (%d, %d)\n", finalBottom, finalRight); printf("Max sum is: %d\n", maxSum); } // Driver program to test above functions int main() { int M[ROW][COL] = {{1, 2, -1, -4, -20}, {-8, -3, 4, 2, 1}, {3, 8, 10, 1, 3}, {-4, -1, 1, 7, -6} }; findMaxSum(M); return 0; }
Maximum Submatrix & Largest Rectangle