首先将原问题转化为最大子矩阵和问题:
0 -> 1
1 -> -1000
对于最大子矩阵和问题,用i,j表示行数,用k表示列数,那么利用前缀和,我们可以把问题转化为求夹在第i行和第j行之间的最大子矩形和,也就是一维的最大子序列和问题了。
完整代码:
/*0.016s*/
#include<bits/stdc++.h>
using namespace std;
const int _INF = -1000;
int num[105][105];
int max_mat_sum(int n, int m)
{
int i, j, k, temp, maxn = 0;
///从上往下,从左往右
for (i = 1; i <= n; ++i)
for (j = i; j <= n; ++j)
{
temp = 0;
for (k = 1; k <= m; ++k)
{
if (temp >= 0) temp += num[j][k] - num[i - 1][k];
else temp = num[j][k] - num[i - 1][k];
maxn = max(maxn, temp);
}
}
return maxn;
}
int main()
{
int n, m, i, j;
while (~scanf("%d%d", &n, &m), n)
{
for (i = 1; i <= n; ++i)
for (j = 1; j <= m; ++j)
{
scanf("%d", &num[i][j]);
num[i][j] = (num[i][j] ? _INF : 1);///把有树的位置设置成一个很小的数,但不要太小
num[i][j] += num[i - 1][j]; ///累加每一列
}
printf("%d\n", max_mat_sum(n, m));
}
return 0;
}