题目:https://cn.vjudge.net/problem/UVA-10827
题意:给一个大小不超过75*75的方阵,里面是-100到100的整数,让你求子矩阵里的元素和最大值。这个矩阵有一个特点,矩阵上下、左右是认为是相邻的,所以取可以取类似下图的子矩阵。

思路:这个球面矩阵的特殊性可以用一个简单的技巧的解决,将四个相同的方阵拼在一起就可以忽略它的特殊性。直接枚举复杂度高达O(n^6),于是我们可以先预处理出二维前缀和,然后四层循环枚举子矩阵O(1)查询元素和,复杂度O(n^2 + n^4)
关于二维前缀和怎么预处理和查询可以看看这篇博客,思想和一维前缀和类似
https://www.cnblogs.com/OIerShawnZhou/p/7348088.html
代码:c++
#include <cstdio>
#include <iostream>
#include <cmath>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
#include <map>
#include <cstring>
#include <set>
#include <stack>
#include <cstdlib>
#include <bitset>
using namespace std;
const int maxn = 150 + 10;
int n;
long long a[maxn][maxn];
long long pre[maxn][maxn];
void init()
{
memset(pre, 0, sizeof(pre));
for(int i = 1; i <= 2 * n; i++)
{
for(int j = 1; j <= 2 * n; j++)
{
pre[i][j] = pre[i - 1][j] + a[i][j];
}
}
for(int i = 1; i <= 2 * n; i++)
{
for(int j = 1; j <= 2 * n; j++)
{
pre[i][j] += pre[i][j - 1];
}
}
}
inline long long getsum(int x, int y, int r, int c)
{
return pre[x + r - 1][y + c - 1] - pre[x + r - 1][y - 1] - pre[x - 1][y + c - 1] + pre[x - 1][y - 1];
}
int main()
{
int T;
cin >> T;
while (T--)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
scanf("%lld", &a[i][j]);
a[i + n][j] = a[i][j + n] = a[i + n][j + n] = a[i][j];
}
}
init();
long long ans = (long long)-1e15;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= n; j++)
{
for(int r = 1; r <= n; r++)
{
for(int c = 1; c <= n; c++)
{
ans = max(ans, getsum(i, j, r, c));
}
}
}
}
cout << ans << endl;
}
return 0;
}
本文介绍了一种解决球面矩阵中寻找最大子矩阵和问题的方法。通过将矩阵拼接成更大矩阵来消除边界效应,并利用二维前缀和进行快速查询,最终达到O(n^2+n^4)的时间复杂度。
1251

被折叠的 条评论
为什么被折叠?



