vojos 1055,1057 最大子矩阵、正方形

来源:互联网 发布:南京银行上海分行知乎 编辑:程序博客网 时间:2024/05/29 03:17

一个是求最大矩阵、一个是求最大正方形,虽说求最大矩阵也可以求最大正方形,但是求最大正方形有更好的dp方法。所以列出来区别一下

vijos1055

浅谈用极大化思想解决最大子矩形问题--王知昆请戳这里学习学习

每次枚举一个点(以这个点产生上下左右边界),模拟接着枚举下一个点,更新最大值以及上下边界即可

一共从左往右、从右往左各扫一次,上下界特判

像这个是无法从左往右扫出来的,但是可以从右往左扫出来。

#include <map>#include <set>#include <queue>#include <stack>#include <math.h>#include <vector>#include <cstdio>#include <string>#include<string.h>#include <fstream>#include <iostream>#include <algorithm>using namespace std;#define exp 1e-8#define INF 100000000#define ll long long#define set(a,b) memset(a,b,sizeof(a));void bug(string st="bug"){cout<<st<<endl;}template<typename __ll>inline void read(__ll &m){    __ll x=0,f=1;char ch=getchar();    while(!(ch>='0'&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    m=x*f;}const int maxn=5010;struct p{    int x,y;}point[maxn];int l,w;int n,ans=0;bool cmpLR(p a,p b){    if(a.y-b.y)        return a.y<b.y;    return a.x<b.x;}bool cmpl(p a,p b){    if(a.x-b.x)        return a.x<b.x;    return a.y<b.y;}bool cmpr(p a,p b){    if(a.x-b.x)        return a.x>b.x;    return a.y<b.y;}void findLR()//特判上下边界{    int temp=0;    sort(point+1,point+1+n,cmpLR);    for(int i=2;i<=n;i++)        if(point[i].y!=point[i-1].y)            temp=max(temp,point[i].y-point[i-1].y);    ans=max(temp*l,ans);}void find(int lr)//左右、右左{    if(lr==1)        sort(point+1,point+1+n,cmpl);    else        sort(point+1,point+1+n,cmpr);    for(int i=1;i<=n;i++)    {        int d=0,u=w;        for(int j=i+1;j<=n;j++)            if(point[j].x==point[i].x||point[j].y>u||point[j].y<d)                continue;            else            {                ans=max(ans,(u-d)*abs(point[j].x-point[i].x));                if(point[j].y>=point[i].y) u=point[j].y;//如果point[j].y==point[i].y                if(point[j].y<=point[i].y) d=point[j].y;//则可以从另一个方向扫出来。                if(d>=u)break;            }    }}int main(){    read(l),read(w),read(n);    for(int i=1;i<=n;i++)        read(point[i].x),read(point[i].y);    point[++n].x=0,point[++n].y=0;    point[++n].x=0,point[++n].y=w;    point[++n].x=l,point[++n].y=0;    point[++n].x=l,point[++n].y=w;    findLR();    find(1);    find(-1);    cout<<ans<<endl;    return 0;}


Vijos 1057

设f[i][j]表示以(i,j)为顶点的最大的正方形,当s[i][j]==1则通过min(s[i-1][j-1],min(s[i-1][j],s[i][j-1]))+1更新s[i][j]即可

可以自行画图理解一下

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



0 0
原创粉丝点击