UVa 108 - Maximum Sum

  题目大意:给一个矩阵,找出一个元素之和最大的子矩阵。

  可以暴力枚举,不过是时间复杂度是O(n6),通过利用一个sum数组保存已计算的和可以提高效率(sum[i][j]保存从矩阵左上角到m[i][j]的所有元素和),把时间复杂度降为O(n4),都说这是DP,可是我怎么感觉不出来?对DP理解不够深刻的原因吗?

 1 #include <cstdio>
 2 #define MAXN 105
 3 
 4 int a[MAXN][MAXN], sum[MAXN][MAXN];
 5 
 6 int main()
 7 {
 8 #ifdef LOCAL
 9     freopen("in", "r", stdin);
10 #endif
11     int n;
12     while (scanf("%d", &n) != EOF)
13     {
14         for (int i = 1; i <= n; i++)
15             for (int j = 1; j <= n; j++)
16                 scanf("%d", &a[i][j]);
17         for (int i = 0; i <= n; i++) 
18             sum[i][0] = sum[0][i] = 0;
19         for (int i = 1; i <= n; i++)
20             for (int j = 1; j <= n; j++)
21                 sum[i][j] = sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1] + a[i][j];
22         int max = a[1][1];
23         for (int i = 1; i <= n; i++)
24             for (int p = i; p <= n; p++)
25                 for (int j = 1; j <= n; j++)
26                     for (int q = j; q <= n; q++)
27                     {
28                         int t = sum[p][q] - sum[p][j-1] - sum[i-1][q] + sum[i-1][j-1];
29                         if (t > max)   max = t;
30                     }
31         printf("%d\n", max);
32     }
33     return 0;
34 }
View Code

   还可以进行进一步的优化,将时间复杂度降到O(n3),主要思想就是将二维转化为一维。先枚举行,比如把子矩阵行范围限制在i行到p行之间,然后求这个行范围内每列的和,这样就转化成了一维的最大连续和问题。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <climits>
 4 using namespace std;
 5 #define MAXN 105
 6 
 7 int a[MAXN][MAXN], sum[MAXN][MAXN];
 8 
 9 int column_sum(int i, int p, int j)
10 {
11     return sum[p][j] - sum[p][j-1] - sum[i-1][j] + sum[i-1][j-1];
12 }
13 
14 int main()
15 {
16 #ifdef LOCAL
17     freopen("in", "r", stdin);
18 #endif
19     int n;
20     while (scanf("%d", &n) != EOF)
21     {
22         for (int i = 0; i <= n; i++) 
23             sum[i][0] = sum[0][i] = 0;
24         for (int i = 1; i <= n; i++)
25             for (int j = 1; j <= n; j++)
26             {
27                 scanf("%d", &a[i][j]);
28                 sum[i][j] = sum[i][j-1] + sum[i-1][j] - sum[i-1][j-1] + a[i][j];
29             }
30         int gMax = a[1][1];
31         for (int i = 1; i <= n; i++)
32             for (int p = i; p <= n; p++)
33             {
34                 int sum = 0, minSum = 0, lMax = INT_MIN;
35                 for (int j = 1; j < n; j++)
36                 {
37                     sum += column_sum(i, p, j);
38                     lMax = max(lMax, sum - minSum);
39                     minSum = min(minSum, sum);
40                 }
41                 if (lMax > gMax)  gMax = lMax;
42             }    
43         printf("%d\n", gMax);
44     }
45     return 0;
46 }
View Code

 

posted @ 2013-08-16 20:53  xiaobaibuhei  阅读(378)  评论(0编辑  收藏  举报