曾记否,到中流击水,浪遏飞舟。|

Moyyer_suiy

园龄:2年8个月粉丝:4关注:18

syoj 1824. 剪纸题解

题目链接

给你一个 01 矩阵,求满足第一行、最后一行、第一列、最后一列均无 0 的最大子矩阵面积。n,m<=200

不难想到对于每个点,预处理出,向其上下左右最大限度扩展。这种方法类似于单调栈的预处理。

预处理后,以每个点为矩阵左上角,向右下枚举矩阵右上角。此时我们已经确定了这个矩阵的第一行、第一列满足条件,只需判断最后一行和最后一列是否满足条件即可。

加上一些优化。我们认为这样的复杂度大概能被允许。

#include<bits/stdc++.h>
using namespace std;
const int N=202;
int n,m;
int a[N][N];
int s[N][N][5];
//0上1下2左3右
int ans;
int main(){
    scanf("%d%d",&n,&m);
    memset(a,-1,sizeof a);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            char c;
            cin>>c;
            if(c=='X') a[i][j]=0;
            else a[i][j]=1;
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            for(int q=i;q>=1;q--){
                if(!a[q][j]) break;
                s[i][j][0]=q;
            }
            for(int q=i;q<=n;q++){
                if(!a[q][j]) break;
                s[i][j][1]=q;
            }
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            for(int q=j;q>=1;q--){
                if(!a[i][q]) break;
                s[i][j][2]=q;
            }
            for(int q=j;q<=m;q++){
                if(!a[i][q]) break;
                s[i][j][3]=q;
            }
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(!a[i][j]) continue;
            if((s[i][j][1]-s[i][j][0]+1)*(s[i][j][3]-s[i][j][2]+1)<=ans) continue;
            for(int x=i;x<=s[i][j][1];x++){
                for(int y=j;y<=s[i][j][3];y++){
                	if(!s[x][y][0]||!s[x][y][2]) continue;
                    if(s[x][y][0]<=i&&s[x][y][2]<=j)
                        ans=max(ans,(x-i+1)*(y-j+1));
                }
            }
            if(ans==n*m){
                printf("%d",ans);
                return 0;
            }
        }
    printf("%d",ans);
    return 0;
}

本文作者:Moyyer_suiy

本文链接:https://www.cnblogs.com/Moyyer-suiy/p/17911719.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Moyyer_suiy  阅读(18)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起