• UVa 108


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

      可以暴力枚举,不过是时间复杂度是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
    ", 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
    ", gMax);
    44     }
    45     return 0;
    46 }
    View Code
  • 相关阅读:
    iOS 109个Demo范例
    iOS 109个Demo范例
    iOS 完全复制UIView
    iOS 完全复制UIView
    iOS 获取self类型
    Python 进阶_OOP 面向对象编程_类和继承
    Python 进阶_OOP 面向对象编程_类和继承
    Python 进阶_模块 & 包
    Python 进阶_模块 & 包
    Python 进阶_模块 & 包
  • 原文地址:https://www.cnblogs.com/xiaobaibuhei/p/3263507.html
Copyright © 2020-2023  润新知