题目给一个h*w的矩阵,每个点是0或者1;找出只包含0的最大矩形;
为了方便处理,我把所有是0的点换成了1,所有是1的点换成了0;
然后对于每个点,我求出其上方所有的1的长度,然后把每一行看作是一个有不同高度的直方图;
比如图中是一个4 × 6的矩形,画出红色的是我们要找到的区域。
我们把这个矩阵转换成:
然后我们只要对每个点调用一次直方图求最大矩阵算法就可以得出结果了;(该算法链接)
最终代码如下:
#include <cstdio>
#include <iostream>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;
const int maxx=1406;
int h,w;
vector<vector<int> > A(maxx,vector<int>(maxx,0));
int countArea(vector<int> A, int n) {
int ans=0,sun=0;
pair<int ,int > temp;
stack<pair<int ,int > > s;
for(int i=0;i<n;i++){
while(!s.empty() && s.top().first>=A[i]){
temp=s.top();s.pop();
ans=max(ans,temp.first*(temp.second+sun));
sun+=temp.second;
}
s.push(make_pair(A[i],1+sun));
sun=0;
}
while(!s.empty()){
temp=s.top();s.pop();
ans=max(ans,temp.first*temp.second);
if(!s.empty()) s.top().second+=temp.second;
}
return ans;
}
int main(){
int x,ans=0;
cin>>h>>w;
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
cin>>x;
A[i][j]=!x;
}
}
for(int i=1;i<h;i++){
for(int j=0;j<w;j++){
if(A[i][j]!=0) A[i][j]=A[i-1][j]+1;
}
}
for(int i=0;i<h;i++){
ans=max(ans,countArea(A[i],w));
}
cout<<ans<<endl;
return 0;
}
错点:
1.以为countArea函数用的是vector,现在补充一下初始化vector的方法:
对于一维vector的初始化,除了可以
vector<int > A;
A.resize(h);
还可以
vector<int > A(h,0);//把A[0]-A[h-1]初始化为0;
还可以
int a[5]={1,2,3,4,5};
vector<int> A(a,a+5);//把A初始化为[a,a+5)的值,左闭右开区间;
对于二维vector就可以:
vector<vector<int> > A;
A.resize(h);
for(int i=0;i<h;i++){
A[i].resize(w);
}
也可以:
vector<vector<int> > A(h,vector<int>(w,0));//把A中[0,h-1]行[0,w-1]列的元素都初始化为0;