dp例题03. 最大子矩阵和

题目Description

   给出一个矩阵, 求子矩阵(可以是其本身)数之和的最大值

Input

  第一行 为行数n和列数m       (n500, m500)

  接下来为一个n行m列的矩阵 (每个值ai,1000 ≤ a≤ 1000)

Output

 子矩阵(可以是其本身)数之和的最大值

Sample Input:

4  4

0 -2 -7  0

9  2 -6  2

-4 1 -4  1

-1 8  0  -2

Sample Output

   15

解题思路:

 解法1:单纯用二维前缀和  时间复杂度O(n*n*m*m);(TLE)

 解法2:dp+前缀和  时间复杂度O(n*n*m) 或O(n*m*m)

  如果是求一维的最长子序列 我们会用O(n)的时间复杂度求出

  而这里为二维的, 能否用一维的解法思想去转化一下?

       刚开始从行数遍历(不裁剪列数情况下)所有的子矩阵, 需要O(n²)时间, 之后对于这样遍历的子矩阵进行求解最大和,能否利用O(m)时间完成求解

         遍历后的二维子矩阵可以一维数组化(即 将 单列上的数相加为一个数, 构造出plus数组), 再利用求一维最长子序列的思想(O(m)时间复杂度)即可

       构造plus数组:利用每一列上的前缀和, 比如求第 k 列上第 i 行到第 j 行的数之和 plus[k] = col_sum[j][k] - col_sum[i-1][k];   O(1) 时间复杂度

     单独构造col_sum数组: O(n*m)时间复杂度

以下为c语言代码(解法2)

 1 #include <stdio.h>
 2 int a[501][501], col_sum[501][501];
 3 int max_subsequence(int * a, int n) {
 4     int sum = -1e7, max = -1e7;
 5     for (int i = 0; i < n; i++) {
 6         sum = (sum + a[i] > a[i])? sum + a[i] : a[i];
 7         max = (sum > max)? sum : max;
 8     }
 9     return max;
10 }
11 int main() {
12     int row, col, plus[501];
13     scanf("%d%d", &row, &col);
14     for (int i = 0; i < row; i++) {
15         for (int j = 0; j < col; j++) {
16             scanf("%d", &a[i][j]);
17         }
18     }
19     for (int j = 0; j < col; j++) {
20         for (int i = 0; i < row; i++) {
21             if (i == 0) {
22                 col_sum[i][j] = a[i][j];
23             }
24             else {
25                 col_sum[i][j] = col_sum[i-1][j] + a[i][j];
26             }
27         }
28     }
29     int ans = -1e7;
30     for (int i = 0; i < row; i++) {
31         for (int k = i; k < row; k++) {
32             if (i == 0) {
33                 for (int j = 0; j < col; j++) {
34                     plus[j] = col_sum[k][j];
35                 }
36                 int temp = max_subsequence(plus, col);
37                 ans = (temp > ans) ? temp : ans;
38             }
39             else {
40                 for (int j = 0; j < col; j++) {
41                     plus[j] = col_sum[k][j] - col_sum[i-1][j];
42                 }
43                 int temp = max_subsequence(plus, col);
44                 ans = (temp > ans) ? temp : ans;
45             }
46         }
47     }
48     printf("%d\n", ans);
49     return 0;
50 }

 

 

posted on 2020-04-04 13:49  y2ek  阅读(257)  评论(0)    收藏  举报

导航