题意:
给你一个n*m的只有 1 和 0 的矩阵, 求全是1的第二大的子矩阵的面积。
题目链接:
https://ac.nowcoder.com/acm/contest/882/H
题解:
听说是陈年老题,可惜我不会
比赛一直在改就是不知道哪里错了qaq
比赛后看到有人用暴力写法A过了,惊了,我copy了他的代码交了一发,tle,牛客的服务器让我觉得好迷
然后看了队友的单调栈写法发现全是 1000*1000 个 1 暴力肯定会T 好迷啊
做法:
首先,先预处理,把h[i][j] 作为以h[i][j]作为最低点的连续的1的长度, 如果该点为0,则长度为 0。
然后对每一行进行单调栈处理, 对计算的结果取值,由于使用单调栈,我们求得是次大子矩阵,所以要把包含在最大子矩阵得次大
子矩阵的情况算进去,所以对于取值的时候要特判 (x-1,y) 和 (x,y-1),x代表长,y代表宽。
AC_code:
/*
Algorithm:
Author: anthony1314
Creat Time:
Time Complexity:
*/
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cstring>
#include<cstdio>
//#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define mod 1e9 + 7
#define line printf("--------------");
using namespace std;
int h[maxn][maxn];
int maxx = 0, maxx1 = 0;
int calc(int x, int y) {
int ans = x * y;
if(ans > maxx) {
maxx1 = maxx;
maxx = ans;
} else if(ans > maxx1) {
maxx1 = ans;
}
}
int main() {
int n, m;
cin>>n>>m;
char s;
memset(h, 0, sizeof(h));
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
cin>>s;
if(s == '1') {
h[i][j] = h[i-1][j] + 1;
}
}
}
for(int i = 1; i <= n; i++) {
stack<int>st;
st.push(0);
h[i][0] = -2;//防止栈空
h[i][m + 1] = -1;
for(int j = 1; j <= m+1; j++) {
while (h[i][st.top()] > h[i][j]) {
int index = st.top();
st.pop();
int d = j-1-st.top(); //当前位置往前
calc(d, h[i][index]);//最大的情况
calc(d-1, h[i][index]);//包含在最大内的次大的情况
calc(d, h[i][index]-1);
}
st.push(j);
}
}
cout<<maxx1<<endl;
return 0;
}
暴力代码(WA):
/*
Algorithm:
Author: anthony1314
Creat Time:
Time Complexity:
*/
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
#include<stack>
#include<cstring>
#include<cstdio>
//#include<bits/stdc++.h>
#define ll long long
#define maxn 1005
#define mod 1e9 + 7
#define line printf("--------------");
using namespace std;
int h[maxn][maxn];
int main() {
int n, m;
int maxx = 0, maxx1 = 0;
cin>>n>>m;
char s;
memset(h, 0, sizeof(h));
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
cin>>s;
if(s == '1') {
h[i][j] = h[i-1][j] + 1;
}
}
}
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
int hh = h[i][j];
int d = 1;
while(hh != 0){
int ans = hh*d;
if(ans > maxx){
maxx1 = maxx;
maxx = ans;
}else if(ans > maxx1){
maxx1 = ans;
}
hh = min(hh, h[i][j+d]);
++d;
}
}
}
cout<<maxx1<<endl;
return 0;
}