九度 1497

九度 1497 面積最大全1子矩陣

先預處理出每行連續1的個數,sum[i][j]表示第i行中到第j列爲止的連續1的個數。

for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        if(a[i][j])
            sum[i][j]=sum[i][j-1]+a[i][j];
        else
            sum[i][j]=0;

枚舉i,j,並找出以sum[i][j]爲寬的最大長度。

這樣得到的便是以sum[i][j]爲寬的最大子矩陣。
但這樣的複雜度還是太高,我們需要一些輔助手段來優化。
再根據sum預處理列,ma[i][j]用來初步估算以sum[i][j]爲寬的全1子矩陣的面積。每次求取時先用ans與ma[i][j]比較,ma[i][j]>ans說明以sum[i][j]爲寬有可能得到面積更大的全1子矩陣,這樣能夠初步篩去一些明顯得不到最大矩陣的情況,避免無謂操作。

void set_col(int c){//get ma[i][c]  
    for(int i=1;i<=n;i++){
        if(!sum[i][c]) continue;
        int ti=i;
        int tsum=0;
        while(sum[ti][c]){
            tsum+=sum[ti][c];
            ti++;
        }
        for(int j=i;j<ti;j++)
            ma[j][c]=tsum;
        i=ti;
    }
}
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1005;
const LL Inf=1e18;
int a[maxn][maxn];
int sum[maxn][maxn];
int ma[maxn][maxn];
int n, m;
void set_col(int c){//get ma[i][c]  
    for(int i=1;i<=n;i++){
        if(!sum[i][c]) continue;
        int ti=i;
        int tsum=0;
        while(sum[ti][c]){
            tsum+=sum[ti][c];
            ti++;
        }
        for(int j=i;j<ti;j++)
            ma[j][c]=tsum;
        i=ti;
    }
}
int main(){
    int ans=0;

//      freopen("matrix.in","r",stdin);//從in.txt中讀取數據
//      freopen("matrix.out","w",stdout);//輸出到out.txt文件
    while(~scanf("%d%d",&n, &m)){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
        }
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        if(a[i][j])
            sum[i][j]=sum[i][j-1]+a[i][j];
        else
            sum[i][j]=0;
        memset(ma,0,sizeof(ma));
        for(int j=1;j<=m;j++){
            set_col(j);
        }

        ans=0;
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        if(sum[i][j]&&ans<ma[i][j]){
            int cnt=1;
            for(int k=i-1;k>0;k--){
                if(sum[i][j]>sum[k][j]) break;
                cnt++;
            }
            for(int k=i+1;k<=n;k++){
                if(sum[i][j]>sum[k][j]) break;
                cnt++;
            }
            ans=max(ans,cnt*sum[i][j]);
        }
        printf("%d\n",ans);
    }

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章