最大01子矩阵 例题:POJ3494
代码实现有些许复杂
#include<cstdio>
#include<stack>
using namespace std;
const int N=2e3+10;
int n,m,a[N][N],h[N][N],l[N][N],r[N][N];
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j) h[i][j]=l[i][j]=r[i][j]=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
scanf("%d",&a[i][j]);
if(a[i][j]) h[i][j]=h[i-1][j]+1;
}
}
//预处理左区间
for(int i=1;i<=n;++i){
stack<int>sta;
sta.push(0);
h[i][0]=-1;
for(int j=1;j<=m;++j) {
if(h[i][j]==0) {
while(sta.size()) sta.pop();
sta.push(j);
continue;
}
if(h[i][j]>h[i][sta.top()]){
sta.push(j);
l[i][j]=j;
continue;
}
while(h[i][j]<=h[i][sta.top()]) sta.pop();
l[i][j]=sta.top()+1;
//printf("i:%d sz:%d\n",i,sta.size());
sta.push(j);
}
}
//预处理右区间
//puts("***");
for(int i=1;i<=n;++i){
h[i][m+1]=-1;
stack<int>sta;
sta.push(m+1);
for(int j=m;j>=1;--j){
if(h[i][j]==0){
while(sta.size()) sta.pop();
sta.push(j);
continue;
}
if(h[i][j]>h[i][sta.top()]){
sta.push(j);
r[i][j]=j;
continue;
}
while(h[i][j]<=h[i][sta.top()]) sta.pop();
r[i][j]=sta.top()-1;
sta.push(j);
}
}
// puts("h");
// for(int i=1;i<=n;++i){
// for(int j=1;j<=m;++j) printf("%d ",h[i][j]);
// puts("");
// }
// puts("l");
// for(int i=1;i<=n;++i){
// for(int j=1;j<=m;++j) printf("%d ",l[i][j]);
// puts("");
// }
// puts("r");
// for(int i=1;i<=n;++i){
// for(int j=1;j<=m;++j) printf("%d ",r[i][j]);
// puts("");
// }
int ans=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
if(h[i][j])
ans=max(ans,(r[i][j]-l[i][j]+1)*h[i][j]);
}
}
printf("%d\n",ans);
}
}
/*
5 5
0 1 0 1 0
1 1 0 1 0
1 1 1 1 1
1 1 1 1 1
0 0 0 0 0
*/
F-Animal Protection
做法:对于每个下表i 的贡献就是 (i-l[i]+1)*(r[i]-i+1)*h[i] 但是这样似乎有重复计算的,解决也很简单,就是预处理l[i]是保持严格递增,预处理r[i]是保持不递减就可以了。
#include<cstdio>
#include<stack>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
const int N=2e3+10;
int n,m,h[N][N],l[N][N],r[N][N];
char s[N][N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%s",s[i]+1);
for(int j=1;j<=m;++j){
if(s[i][j]=='O') h[i][j]=h[i-1][j]+1;
}
}
for(int i=1;i<=n;++i){
stack<int>sta;
sta.push(0);
for(int j=1;j<=m;++j){
if(h[i][j]==0){
while(sta.size()) sta.pop();
sta.push(j);
continue;
}
if(h[i][j]>h[i][sta.top()]) {
l[i][j]=j;
sta.push(j);
continue;
}
while(h[i][j]<h[i][sta.top()]) sta.pop();//注意这里是小于,下面求r是小于等于
l[i][j]=sta.top()+1;
sta.push(j);
}
}
for(int i=1;i<=n;++i){
stack<int>sta;
sta.push(m+1);
for(int j=m;j;--j){
if(h[i][j]==0){
while(sta.size()) sta.pop();
sta.push(j);
continue;
}
if(h[i][j]>h[i][sta.top()]) {
r[i][j]=j;
sta.push(j);
continue;
}
while(h[i][j]<=h[i][sta.top()]) sta.pop();
r[i][j]=sta.top()-1;
sta.push(j);
}
}
ll ans=0;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
ans=(ans+(r[i][j]-j+1)*(j-l[i][j]+1)%mod*h[i][j]%mod)%mod;
//printf("i:%d j:%d %d\n",i,j,(r[i][j]-j+1)*(j-l[i][j]+1)%mod*h[i][j]%mod);
}
}
printf("%lld\n",ans);
}