- 題目描述:
-
已知矩陣的大小定義為矩陣中所有元素的和。給定一個矩陣,你的任務是找到最大的非空(大小至少是1 * 1)子矩陣。
比如,如下4 * 4的矩陣
0 -2 -7 0
9 2 -6 2
-4 1 -4 1
-1 8 0 -2
的最大子矩陣是
9 2
-4 1
-1 8
這個子矩陣的大小是15。
- 輸入:
-
輸入是一個N * N的矩陣。輸入的第一行給出N (0 < N <= 100)。
再后面的若干行中,依次(首先從左到右給出第一行的N個整數,再從左到右給出第二行的N個整數……)給出矩陣中的N2個整數,整數之間由空白字符分隔(空格或者空行)。
已知矩陣中整數的范圍都在[-127, 127]。
- 輸出:
-
測試數據可能有多組,對於每組測試數據,輸出最大子矩陣的大小。
- 樣例輸入:
-
4 0 -2 -7 0 9 2 -6 2 -4 1 -4 1 -1 8 0 -2
- 樣例輸出:
-
15
第一映像是暴力枚舉,不過顯然會超時,然后就想到了DP。其實因為矩陣肯定是對齊的,所以如我們將兩行加起來求最大子數組就可以得到一個行數為2的子矩陣。所以問題就轉化成了求一個數組的最大子數組和。然后就是枚舉第i行到第j行相加得到的數組了。注意res的值不能設為0,因為可能最后的結果是負數。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 int N; 7 int a[101][101]; 8 int dp[101]; 9 10 int getMaxArray(int a[], int N) { 11 int max = a[0], tmp = 0; 12 for (int i = 0; i < N; ++i) { 13 if (tmp > 0) { 14 tmp += a[i]; 15 } else { 16 tmp = a[i]; 17 } 18 max = max > tmp ? max : tmp; 19 } 20 return max; 21 } 22 23 int main() { 24 //freopen("input.txt", "r", stdin); 25 while (scanf("%d", &N) != EOF) { 26 for (int i = 0; i < N; ++i) { 27 for (int j = 0; j < N; ++j) { 28 scanf("%d", &a[i][j]); 29 } 30 } 31 int res = a[0][0], tmp; 32 for (int i = 0; i < N; ++i) { 33 memset(dp, 0, sizeof(dp)); 34 for (int j = i; j < N; ++j) { 35 for (int k = 0; k < N; ++k) { 36 dp[k] += a[j][k]; 37 } 38 tmp = getMaxArray(dp, N); 39 res = res > tmp ? res : tmp; 40 } 41 } 42 printf("%d\n", res); 43 } 44 return 0; 45 } 46 47 /************************************************************** 48 Problem: 1139 49 User: hupo250 50 Language: C++ 51 Result: Accepted 52 Time:60 ms 53 Memory:1560 kb 54 ****************************************************************/