• 【洛谷习题】最大正方形


    题目链接:https://www.luogu.org/problemnew/show/P1387


    最近学OI有点过火,今早上愣是没睡醒,上午的自习就没有了!不过还是很开心,连A三道DP水题。

    这个题的话,思路比较清晰。我们想知道有没有边长为l的正方形,肯定要先知道有没有边长为l-1的正方形。我们枚举一个正方形的左上角,然后搬着一个边长为l-1的正方形在四个角上跑,如果这四个角上的小正方形全是1,那么这个边长为l的正方形肯定也全是1,否则取其中最大的。描述的有点凌乱,看代码就好了。一开始傻了一般开了一个四维数组保存正方形的四个顶点,这样是没有必要的,因为一个左上角的顶点和边长就能确定一个正方形。

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 const int mmax = 105;
     7 
     8 int map[mmax][mmax], dp[mmax][mmax][mmax];
     9 int main() {
    10     int n, m, ans = 1;
    11     scanf("%d%d", &n, &m);
    12     for (int i = 1; i <= n; ++i)
    13         for (int j = 1; j <= m; ++j) {
    14             scanf("%d", &map[i][j]);
    15             if (map[i][j]) dp[i][j][1] = 1;
    16         }
    17     for (int l = 2; l <= min(n,m); ++l) {
    18         for (int i = 1; i <= n - l + 1; ++i)
    19             for (int j = 1; j <= m - l + 1; ++j) {
    20                 if (dp[i][j][l - 1] == l - 1 && dp[i][j + 1][l - 1] == l - 1 && dp[i + 1][j][l - 1] == l - 1 && dp[i + 1][j + 1][l - 1] == l - 1)
    21                     dp[i][j][l] = l;
    22                 else dp[i][j][l] = max(dp[i][j][l - 1], max(dp[i][j + 1][l - 1], max(dp[i + 1][j][l - 1], dp[i + 1][j + 1][l - 1])));
    23                 ans = max(ans, dp[i][j][l]);
    24             }
    25         if (ans < l) break;
    26     }
    27     printf("%d", ans);
    28     return 0;
    29 }
    AC代码

    实际上,这样做也不算太优秀。我们可以定义dp[i][j]表示以(i,j)为右下角的最大正方形的边长。那么对于map[i][j]==1,则有dp[i][j]=min(dp[i-1][j-1],min(dp[i-1][j],dp[i][j-1]))+1。显然是对的,每次考虑能否将(i,j)加入到已有的正方形中,那他一定可以加入以(i-1,j-1)、(i-1,j)、(i,j-1)为右下角的最大正方形中最小的那个,因为最大正方形要求里面全是1。

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 const int mmax = 105;
     7 
     8 int dp[mmax][mmax];
     9 
    10 int main() {
    11     int n, m, point, ans = 0;
    12     scanf("%d%d", &n, &m);
    13     for (int i = 1; i <= n; ++i)
    14         for (int j = 1; j <= m; ++j) {
    15             scanf("%d", &point);
    16             if (point) {
    17                 dp[i][j] = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1;
    18                 ans = max(ans, dp[i][j]);
    19             }
    20         }
    21     printf("%d", ans);
    22     return 0;
    23 }
    AC代码(更优秀)
  • 相关阅读:
    Spring模板方法模式及Callback
    vc新线程、类外控制EDIT控件
    OpenGL绘制框架
    回调函数c++
    matlab练习程序(求灰度图像最大灰度,最小灰度,平均灰度)
    OpenGL绘制函数
    matlab练习程序(图像傅里叶变换,幅度谱,相位谱)
    多项式系数提取算法 c++
    OpenGL绘制复杂图形
    matlab练习程序(图像加噪,各种滤波)
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9613417.html
Copyright © 2020-2023  润新知