C - To the Max POJ - 1050 (子矩阵最大和)

思路

  • 题意
  1. 给我们一个n*n的矩阵,让我们在这个矩阵内找到一个和最大子矩阵,输出这个最大和
  • 分析
  1. 这题的是让求的 二维子区间 最大和,在将这一题的基础上我们先说一下:一维情况下的最大子段和(子区间和):
    1. 举例:给我们一个 n元素的数组 a[], 我们通过下面的代码:
    2. 可以以O(n) 的复杂度求出,最大子段和,这样求的速度很快
int f(int n, int a[])
{
  int mx = 0, b = 0;
  for_(i, 1, n)
  {
      if(b > 0) b += a[i];
      else b = a[i];
      if(mx < b) mx = b;
  }
  return mx;
}
  1. 那么接下来我们继续考虑 二维情况下的最大子矩阵和,我们 做法思路是:通过枚举,一个从 原矩阵 的某一行x,到某一行y的一个子矩阵(子矩阵的列数(设列数为:m)不变),我们通过 这个子矩阵的 每一列所有值想加作为a[]数组对应元素的值,我们就得到了一个 有m个元素的a[]数组,通通过 上面 求一维最大字段和的代码 可以找到,我们枚举的这个 子矩阵中, 能产生的最大子矩阵和了,
  2. 实际上我们的 枚举子矩阵后 求某一列所有元素的和的过程 有一些优化,具体看代码吧

代码

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <queue>
#include <map>
/* #include <unordered_map> */
#include <bitset>
#include <vector>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define ll long long
#define ull unsigned long long
#define db double
#define Pir pair<int, int>
#define PIR pair<Pir, Pir>
#define m_p make_pair
#define INF 0x3f3f3f3f
#define esp 1e-7
#define mod (ll)(1e9 + 7)
#define for_(i, s, e) for(int i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(int i = (ll)(e); i >= (ll)(s); i --)
#define sc scanf
#define pr printf
#define sd(a) scanf("%d", &a)
#define ss(a) scanf("%s", a)
using namespace std;

const int mxn = 105;
int mz[mxn][mxn];
int a[mxn];                 //辅助数组,a[k] 的值为 从mz的某一行到另一行第k列的所有元素的和, 我们要对这个a 数组求 最大字段和,并且把这个最大字段和作为函数返回值返回

int f(int n, int a[])
{
    int mx = 0, b = 0;
    for_(i, 1, n)
    {
        if(b > 0) b += a[i];
        else b = a[i];
        if(mx < b) mx = b;
    }
    return mx;
}

int main()
{
    /* fre(); */
    int n;
    while(sd(n) != EOF)
    {
        for_(i, 1, n)    
            for_(j, 1, n)
            sd(mz[i][j]);
        int ans = 0;
        for_(i, 1, n)           //枚举当前子矩阵从第i行开始
        {
            memset(a, 0, sizeof(a));
            for_(j, i, n)       //遍历从i第行开始的子矩阵,且子矩阵的行数 一次位 j - i + 1;
            {
                for_(k, 1, n)   //a[i] 的值位 从第i行到第j行所第k列的mz中元素和
                    a[k] += mz[j][k];
                ans = max(ans, f(n, a));
            }
        }
        pr("%d\n", ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/107532828