悬线法

介绍
悬线法主要由up[],l[],r[]构成,其含义分别是,在某处符合题目条件的情况下,线条(抽象概念)能走到的最上边,最左边和最右边的位置。
最后统计所有子矩阵中最大的子矩阵。
1.洛谷4147玉蟾宫

点击查看代码
#include<iostream>
#include<vector>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define ll long long
char a[1001][1001];
int up[1001][1001],l[1001][1001],r[1001][1001];

signed main()
{
     cin.tie(NULL);
     cout.tie(nullptr);
     ios_base::sync_with_stdio(false);
     int n,m;
     cin>>n>>m;
     for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
     {
         cin>>a[i][j];
         if(a[i][j]=='F')
         up[i][j]=1;
         l[i][j]=r[i][j]=j;


     }
     for(int i=1;i<=n;i++)
 {
     for(int j=2;j<=m;j++)
     {
         if(a[i][j]=='F'&&a[i][j-1]=='F')
         l[i][j]=l[i][j-1];

     }
     for(int j=m-1;j>=1;j--)
     {
        if(a[i][j]=='F'&&a[i][j+1]=='F')
            r[i][j]=r[i][j+1];
     }
}
      int ans=0;
     for(int i=1;i<=n;i++)
     {
        for(int j=1;j<=m;j++)
        {
            if(a[i][j]=='F'&&a[i-1][j]=='F')
            {
               up[i][j]=up[i-1][j]+1;
               l[i][j]=max(l[i][j],l[i-1][j]);
               r[i][j]=min(r[i][j],r[i-1][j]);

            }
            ans=max(ans,up[i][j]*(r[i][j]-l[i][j]+1));
        }

     }
     cout<<ans*3;
     return 0;
}

2.洛谷1387最大正方形

点击查看代码
#include<iostream>
#include<vector>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define ll long long
int a[1001][1001];
int up[1001][1001],l[1001][1001],r[1001][1001];

signed main()
{
     cin.tie(NULL);
     cout.tie(nullptr);
     ios_base::sync_with_stdio(false);
     int n,m;
     cin>>n>>m;
     for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
     {
         cin>>a[i][j];
         if(a[i][j]==1)
         up[i][j]=1;
         l[i][j]=r[i][j]=j;


     }
     for(int i=1;i<=n;i++)
 {
     for(int j=2;j<=m;j++)
     {
         if(a[i][j]==1&&a[i][j-1]==1)
         l[i][j]=l[i][j-1];

     }
     for(int j=m-1;j>=1;j--)
     {
        if(a[i][j]==1&&a[i][j+1]==1)
            r[i][j]=r[i][j+1];
     }
}
      int ans=0,re=0;
     for(int i=1;i<=n;i++)
     {
        for(int j=1;j<=m;j++)
        {
            if(a[i][j]==1&&a[i-1][j]==1)
            {
               up[i][j]=up[i-1][j]+1;
               l[i][j]=max(l[i][j],l[i-1][j]);
               r[i][j]=min(r[i][j],r[i-1][j]);

            }
            re=min(up[i][j],r[i][j]-l[i][j]+1);
            ans=max(ans,re);
        }

     }
     cout<<ans;
     return 0;
}

3.洛谷1169 棋盘制作

点击查看代码
#include<iostream>
#include<vector>
#include<queue>
#include<bits/stdc++.h>
using namespace std;
#define int long long
//#define ll long long
int a[2001][2001];
int up[2001][2001],l[2001][2001],r[2001][2001];

signed main()
{
     cin.tie(NULL);
     cout.tie(nullptr);
     ios_base::sync_with_stdio(false);
     int n,m;
     cin>>n>>m;
     for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
     {
         cin>>a[i][j];
         up[i][j]=1;
         l[i][j]=r[i][j]=j;


     }
     for(int i=1;i<=n;i++)
 {
     for(int j=2;j<=m;j++)
     {
         if(a[i][j]!=a[i][j-1])
         l[i][j]=l[i][j-1];

     }
     for(int j=m-1;j>=1;j--)
     {
        if(a[i][j]!=a[i][j+1])
            r[i][j]=r[i][j+1];
     }
}
      int ans1=0,ans2=0,re=0;
     for(int i=1;i<=n;i++)
     {
        for(int j=1;j<=m;j++)
        {
            if(i>1)
            {

            if(a[i][j]!=a[i-1][j])
            {
               up[i][j]=up[i-1][j]+1;
               l[i][j]=max(l[i][j],l[i-1][j]);
               r[i][j]=min(r[i][j],r[i-1][j]);

            }
            re=min(up[i][j],r[i][j]-l[i][j]+1);
            ans2=max(ans2,up[i][j]*(r[i][j]-l[i][j]+1));
            ans1=max(ans1,re*re);
        }  }

     }
     cout<<ans1<<'\n';
     cout<<ans2;
     return 0;
}

posted @ 2024-01-26 01:12  WandW  阅读(39)  评论(0)    收藏  举报