既然要找到一个面积第二大的,内部全是1的矩阵,我们可以把0区域看作背景板,1区域看作目标区域,然后从目标区域内寻找这样的矩阵。单调栈自然可以满足这些需求,也就是通过已知高,并维持栈内高的递增性(一般用来找最大值),来求解。
由于这些区域可能并不是连续的,而且还会上下分布,所以对于每一次遍历,要对上方,左方和本点求面积。
//#include<pch.h>
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
const int INF = 0x3f3f3f3f;
using namespace std;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline int lldcin()
{
int tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
///Untersee Boot IXD2(1942)
/**Although there will be many obstructs ahead,
the desire for victory still fills you with determination..**/
/**Last Remote**/
ll length[1350][1350];
ll smax=0, ffmax=0;
ll n, m;
stack<ll>st;
void getarea(ll x, ll y)
{
smax = max(x*y, smax);
if (smax > ffmax)
swap(ffmax, smax);
}
void getmax(ll x, ll y)//三个方向求解
{
getarea(x, y);
getarea(x - 1, y);
getarea(x, y - 1);
}
int DETERMINATION()
{
lldin(n), lldin(m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
scanf("%1lld", &length[i][j]);
length[i][j] += length[i][j] * length[i - 1][j];
}
for (int i = 1; i <= n; i++)
{
while (st.size())
st.pop();
st.push(0);
length[i][0] = length[i][m + 1] = -10010;
for (int j = 1; j <= m + 1; j++)
{
while (length[i][st.top()] > length[i][j])//维持高的递增性
{
int tmp = st.top();
st.pop();
getmax(j - 1 - st.top(), length[i][tmp]);
}
st.push(j);
}
}
printf("%lld\n", smax);
return 0;
}
当然也可以直接对每个点进行枚举,默认“宽”是1,找到一个存在“高”的区域后,扩大宽至高不再存在为止。