最大子矩阵问题--悬线法dp

最大子矩阵问题--悬线法dp

problem:搜索全为1的最大子矩阵

#include<bits/stdc++.h>
using namespace std;
const int N = 2010;
const int inf = 1000000007;
void in(int &x){
    x=0;char c=getchar();
    int y=1;
    while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    x*=y;
}
void o(int x){
    if(x<0){x=-x;putchar('-');}
    if(x>9)o(x/10);
    putchar(x%10+'0');
}
int n,m,i,j,ans,l[N],r[N],h[N],lmax,rmax,a[N][N];
signed main(){
	//输入矩阵
    in(n);in(m);
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){;
            in(a[i][j]);
        }
    }
    for(i=1;i<=m;i++)l[i]=1,r[i]=m;
    for(i=1;i<=n;i++){//枚举每一行
        for(j=lmax=1;j<=m;j++) {//搜索左节点
            if (a[i][j]){//统计l
                h[j]++;//高度增加
                if (lmax > l[j])l[j] = lmax;//最进的左
            }else h[j] = 0, l[j] = 1, r[j] = m, lmax = j + 1;//无悬线,高度置0,重置,l,r的将最左边的可能点更新化为j——1
        }
        for (rmax = j = m; j; j--) {
            if (a[i][j]){
                if (rmax < r[j])r[j] = rmax;//更新右节点
                if ((r[j] - l[j] + 1) * h[j] > ans)ans = (r[j] - l[j] + 1) * h[j];//更新面积
            }else rmax = j - 1;//更新rmax
        }
    }
    printf("%d",ans);
    return 0;
}

P1169 [ZJOI2007]棋盘制作

#include<bits/stdc++.h>
using namespace std;
const int N = 2010;
const int inf = 1000000007;
void in(int &x){
    x=0;char c=getchar();
    int y=1;
    while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
    x*=y;
}
void o(int x){
    if(x<0){x=-x;putchar('-');}
    if(x>9)o(x/10);
    putchar(x%10+'0');
}
int n,m,i,j,ans1,ans,l[N],r[N],h[N],lmax,rmax,a[N][N];
signed main(){
    in(n);in(m);
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            in(a[i][j]);
        }
    }
    for(int i=1;i<=n;i++)a[i][0]=233,a[i][m+1]=233;
    for(int j=1;j<=m;j++)a[0][j]=233,a[n+1][j]=233;
    for(i=1;i<=m;i++)l[i]=1,r[i]=m;
    for(i=1;i<=n;i++){//枚举每一行
        for(j=lmax=1;j<=m;j++) {//搜索左节点
            if (a[i][j]!=a[i-1][j]){//统计l
                h[j]++;//高度增加
            }else h[j]=1,l[j]=1,r[j]=m;
            if(a[i][j]!=a[i][j-1]){
                if( lmax>l[j])l[j]=lmax;
            }else lmax=j,l[j]=j;
        }
        for (rmax = j = m; j; j--) {
            if(a[i][j]!=a[i][j+1]){
                if( rmax < r[j])r[j]=rmax;
            }else rmax=j,r[j]=j;
            if ((r[j] - l[j] + 1) * h[j] > ans)ans = (r[j] - l[j] + 1) * h[j];//更新面积
            ans1 = max(ans1,min(r[j]-l[j]+1,h[j]));
        }
    }
    printf("%d\n%d\n",ans1*ans1,ans);
    return 0;
}
posted @ 2021-04-24 13:59  yesuweiYYYY  阅读(48)  评论(0编辑  收藏  举报