• 20191111最大子矩型问题 | dp


    luogu1387最大正方形

    O(n^2)

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int f[105][105];
     5 //f[i][j]代表以i,j为右下角的前i,j区域内的最大正方形 
     6 int main()
     7 {
     8     int n,m,ans = 0;
     9     scanf("%d%d",&n,&m);
    10     for(int i = 1;i <= n;i ++)
    11     {
    12         for(int j = 1,x;j <= m;j ++)
    13         {
    14             scanf("%1d",&x);
    15             if(x)f[i][j] = min(min(f[i - 1][j],f[i][j - 1]),f[i - 1][j - 1]) + 1;
    16             ans = max(ans,f[i][j]);
    17 //            printf("f[%d][%d]=%d
    ",i,j,f[i][j]);
    18         }
    19     }
    20     printf("%d
    ",ans);
    21     return 0;
    22 }

    luogu1681最大正方形2

    先隔着把数取饭,在按最大正方形1操作

    O(n^2)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 int f[1505][1505][2];
     6 int a[1505][1505];
     7 //f[i][j]代表以i,j为右下角的前i,j区域内的最大正方形 
     8 int main()
     9 {
    10     int n,m,ans = 0;
    11     scanf("%d%d",&n,&m);
    12     for(int i = 1;i <= n;i ++)
    13     {
    14         for(int j = 1,x;j <= m;j ++)
    15         {
    16             scanf("%1d",&a[i][j]);
    17         }
    18     }
    19     for(int i = 1;i <= n;i ++)
    20     {
    21         for(int j = 1;j <= m;j ++)
    22         {
    23             if((i%2&&j%2)||(i%2==0)&&(j%2==0))a[i][j] ^= 1;
    24             else continue;
    25         }
    26     }
    27 //    for(int i =1 ;i <= n;i ++)
    28 //    {
    29 //        for(int j = 1;j <= m;j ++)printf("%d",a[i][j]);
    30 //        printf("
    ");
    31 //    }
    32     memset(f,0,sizeof(f));
    33     for(int i = 1;i <= n;i ++)
    34     {
    35         for(int j = 1;j <= m;j ++)
    36         {
    37             if(a[i][j])
    38             {
    39                 f[i][j][1] = min(min(f[i - 1][j][1],f[i][j - 1][1]),f[i - 1][j - 1][1]) + 1;
    40             }
    41             else
    42             {
    43                 f[i][j][0] = min(min(f[i - 1][j][0],f[i][j - 1][0]),f[i - 1][j - 1][0]) + 1;
    44             }
    45 //            printf("f[%d][%d][0]=%d 1:%d
    ",i,j,f[i][j][0],f[i][j][1]);
    46             ans = max(ans,max(f[i][j][0],f[i][j][1]));
    47         }
    48     }
    49     printf("%d
    ",ans);
    50     return 0;
    51 }

    luogu4147玉蟾宫

    题意:

    求n*m矩形中,内部都为F的最大的矩形

    题解:

    看着仿佛和最大正方形一样,其实做法与上面不同,但是这个方法可以适用于上面以及大部分的求最大子矩形的题——悬线法

    在学习悬线法的时候参考了一下题解:[leven][DP专题]悬线法    浅谈用极大化思想解决最大子矩形问题

    l[i][j]表示从i,j点向上延伸的最大矩形的最左边

    r[i][j]表示从i,j点向上延伸的最大矩形的最右边

    up[i][j]表示从i,j点向上延伸的最大矩形的长度,看作从i,j点向上延伸的悬线的长度

    (r[i][j] - l[i][j] + 1)*up[i][j]即为最大矩形的面积

    正确性:因为极大矩形的边界一定是贴着限制点的或贴着边界的,而最大矩形就是极大矩形的最大值,所以在确定悬线的长度时,是遇到限制点才停止的,否则会有更大的矩形能包含这个矩形,那这个矩形就不是极大矩形了,最大矩形也一定不是这个矩形

    时间复杂度:O(nm)

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<iostream>
     4 using namespace std;
     5 int a[1005][1005],l[1005][1005],r[1005][1005],up[1005][1005];
     6 int main()
     7 {
     8     int n,m;
     9     scanf("%d%d",&n,&m);
    10     for(int i = 1;i <= n;i ++)
    11     {
    12         for(int j = 1;j <= m;j ++)
    13         {
    14             char c;
    15             cin>>c;
    16             if(c == 'R')a[i][j] = 0;
    17             else 
    18             {
    19                 a[i][j] = 1;
    20                 l[i][j] = r[i][j] = j;
    21                 up[i][j] = 1;//悬线的长度 
    22             }
    23         }
    24     }
    25 //    for(int i = 1;i <= n;i ++)
    26 //    {
    27 //        for(int j = 1;j <= m;j ++)printf("%d",a[i][j]);
    28 //        printf("
    ");
    29 //    }
    30         
    31     int ans = 0;
    32     for(int i = 1;i <= n;i ++)
    33     {
    34         for(int j = 1;j <= m;j ++)
    35         {
    36             if(a[i][j] == 1 && a[i][j - 1] == 1)l[i][j] = l[i][j - 1];
    37         }
    38         for(int j = m;j >= 1;j --)
    39         {
    40             if(a[i][j] == 1 && a[i][j + 1] == 1)r[i][j] = r[i][j + 1];
    41         }
    42     }
    43     for(int i = 1;i <= n;i ++)
    44     {
    45         for(int j = 1;j <= m;j ++)
    46         {
    47             if(i > 1)
    48             {
    49                 if(a[i][j] == 1 && a[i - 1][j] == 1)
    50                 {
    51                     l[i][j] = max(l[i][j],l[i - 1][j]);
    52                     r[i][j] = min(r[i][j],r[i - 1][j]);
    53                     up[i][j] = up[i - 1][j] + 1;
    54                 }
    55             }
    56 //            printf("l[%d][%d]=%d r[][]=%d up[][]=%d 
    ",i,j,l[i][j],r[i][j],up[i][j]);
    57             int res = (r[i][j] - l[i][j] + 1) * up[i][j];
    58             ans = max(ans,res);
    59         }
    60     }
    61     printf("%d
    ",ans * 3);
    62     return 0;
    63 } 
  • 相关阅读:
    oracle去除字符串中间的空格
    java代理模式
    js方法中的this
    js中访问对象的方法
    Hadoop学习笔记
    查看电脑硬件常用命令
    Ubuntu18.0.4配置Hadoop1.2.1环境
    Entwurfsmuster
    WEB Front-end Development Technology
    Objekt Orientierte Programmierung C++
  • 原文地址:https://www.cnblogs.com/djfuuxjz/p/11837739.html
Copyright © 2020-2023  润新知