P1387 最大正方形

先是传送门:https://www.luogu.com.cn/problem/P1387

这题其实不一定要悬线法(主要是我一看到题目就想到了)

这题实质是要求图里最大正方形(没错,就是我之前的模板)

首先是暴力打法:求二维前缀和,再一波操作

二维前缀和:f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j];

#include <bits/stdc++.h>
using namespace std;
int a[105][105];
int f[105][105];
int main()
{
    int n,m,s,ans=0;
    cin>>n>>m; s=min(n,m);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    cin>>a[i][j],f[i][j]=f[i-1][j]+f[i][j-1]-f[i-1][j-1]+a[i][j];
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    for(int k=ans;k<=s;k++)
    {
        int x=i+k-1; int y=j+k-1;
        if(x>n || y>m || f[i-1][j-1]-f[x][j-1]-f[i-1][y]+f[x][y]!=k*k) break;
        if(ans<k) ans=k;
    }
    cout<<ans;
    return 0;
}

同样,你也可以用普通的DP

公式也很好推:if (a[i][j]==1) f[i][j]=min(min(f[i][j-1],f[i-1][j]),f[i-1][j-1])+1;

#include <iostream>
#include <cstdio>
using namespace std;
int a[101][101],n,m,f[101][101],ans;
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i)
        for (int j=1;j<=m;++j)
        {
            scanf("%d",&a[i][j]);
            if (a[i][j]==1) f[i][j]=min(min(f[i][j-1],f[i-1][j]),f[i-1][j-1])+1;
            ans=max(ans,f[i][j]);
        }
    printf("%d",ans);
}

最后就是悬线法了

#include <bits/stdc++.h>
using namespace std;
int a[105][105],l[105][105],r[105][105],up[105][105];
int main()
{
    int n,m,ans=0;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        cin>>a[i][j];
        l[i][j]=r[i][j]=j;
        up[i][j]=1;
    }
    for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++)
    if(a[i][j] && a[i][j-1]) l[i][j]=l[i][j-1];
    for(int i=1;i<=n;i++)
    for(int j=m;j>=1;j--)
    if(a[i][j] && a[i][j+1]) r[i][j]=r[i][j+1];
    for(int i=2;i<=n;i++)
    for(int j=1;j<=m;j++)
    {
        if(a[i][j]==a[i-1][j]==1)
        {
            l[i][j]=max(l[i][j],l[i-1][j]);
            r[i][j]=min(r[i-1][j],r[i][j]);
            up[i][j]=up[i-1][j]+1;
        }
        int s=min(up[i][j],(r[i][j]-l[i][j]+1))*min(up[i][j],(r[i][j]-l[i][j]+1));//这里主要是求正方形,悬线法的强大无法真正体现 
        ans=max(ans,s);//矩形的话直接就 ans=max(ans,up[i][j]*(r[i][j]-l[i][j]+1)) 
    }
    cout<<sqrt(ans);
    return 0;
}
原文地址:https://www.cnblogs.com/wdxxz3274/p/12070080.html