@(E ACMer)
题意:给你一个矩阵,求它的所有元素和最大的子矩阵.
分析:
我们只知道一维的情况就是经典的最大子段和.然而维数达到二维就变的复杂了.
我们观察数据范围500,易想到 n3 的算法也能过.纯暴力是 n4 的方法
然后可以通过枚举其中一维,dp最后一维的方法求出.
处理列上的和为前缀和,然后枚举列的开头和结尾,形成的段,然后再在行上进行最大子段和复杂度刚好 n3
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <stack>
#include <vector>
#include <string>
#include <queue>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <ctime>
using namespace std;
typedef pair<int, int> pii;
typedef long long ull;
typedef long long ll;
typedef vector<int> vi;
#define xx first
#define yy second
#define rep(i, a, n) for (int i = a; i < n; i++)
#define sa(n) scanf("%d", &(n))
#define vep(c) for(decltype((c).begin()) it = (c).begin(); it != (c).end(); it++)
const int mod = int(1e9) + 7, INF = 0x3fffffff, maxn = 1e5 + 12;
ll a[555][555];
ll dp[555];
int main(void) {
#ifdef LOCALs
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
cin >> T;
while (T--) {
int n, m;
sa(n), sa(m);
memset(a, 0, sizeof(a));
memset(dp,0,sizeof (dp));
for(int i = 1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
scanf("%lld",&a[i][j]);
a[i][j] += a[i-1][j];
}
}
ll max_sum=-INF;
for(int i=1; i<=n; i++)
{
for(int j= 0; j < i; j++)
{
for(int k=1; k<=m; k++)
{
dp[k] = a[i][k]-a[j][k];
dp[k] = max(dp[k], dp[k] + dp[k - 1]);
if(dp[k]>max_sum)
max_sum=dp[k];
}
}
}
printf("%lld\n",max_sum);
}
return 0;
}