![]()

POJ 3494 Largest Submatrix of All 1’s
最大子矩阵:给定M*N的01矩阵,求元素最多且都是1的子矩阵。
4.4常用技巧精选(二)
栈
还是先来跟书上的例题做个对比,借鉴思路。书上的矩形宽为1,底部对齐:

在本题中,将每列中连续的1视作一个宽为1的矩形,就跟例题很像了,只不过底部没有对齐而已。如果我们逐行截断处理,则可视作底部对齐,则每一行构成的子问题都与例题完全一致,取子问题的最大解即为本题的解。
#include <iostream>
using namespace std;
#define MAX_N 2000 + 16
// 输入
int M, N;
int h[MAX_N];
int L[MAX_N], R[MAX_N];
int st[MAX_N]; // 栈
int solve()
{
// 计算L
int t = 0; // 栈的大小
for (int i = 0; i < N; i++)
{
while (t > 0 && h[st[t - 1]] >= h[i])
t--;
L[i] = t == 0 ? 0 : (st[t - 1] + 1);
st[t++] = i;
}
// 计算R
t = 0;
for (int i = N - 1; i >= 0; i--)
{
while (t > 0 && h[st[t - 1]] >= h[i])
t--;
R[i] = t == 0 ? N : st[t - 1];
st[t++] = i;
}
int res = 0; // 注意防止溢出
for (int i = 0; i < N; i++)
{
res = max(res, h[i] * (R[i] - L[i]));
}
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
while (~scanf("%d%d", &M, &N))
{
int ans = 0;
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < M; ++j)
{
int x;
scanf("%d", &x);
h[j] = x ? h[j] + 1 : 0;
}
ans = max(ans, solve());
}
printf("%d\n", ans);
}
#ifndef ONLINE_JUDGE
fclose(stdin);
#endif
return 0;
}
| 16474615 | hankcs | 3494 | Accepted | 192K | 1625MS | C++ | 1193B | 2017-01-14 09:35:55 |
又是一发入魂
例题、这题与《POJ 2082 Terrible Sets》可以构成一个系列,能够有效地训练观察力,直达不同问题的同一本质。
知识共享署名-非商业性使用-相同方式共享:码农场 » POJ 3494 Largest Submatrix of All 1’s 题解《挑战程序设计竞赛》
码农场