zoukankan      html  css  js  c++  java
  • 洛谷P1169 棋盘制作【悬线法】【区间dp】

    题目https://www.luogu.org/problemnew/show/P1169

    题意:n*m的黑白格子,找到面积最大的黑白相间的正方形和矩形。

    思路:传说中的悬线法!用下面这张图说明一下。

    悬线法一般是用来求一个没有障碍点的最大子矩阵的。想象从上面垂下来好多的悬线,这些悬线被一个底所限制,并且可以左右移动但是也有范围限制。

    现在某条悬线可以移动到的面积就是他能满足的子矩形的面积。比如我们已经处理好了$i-1$行,现在考虑$(i,j)$

    对于这道题来说,如果$grid[i][j]!=grid[i-1][j]$就说明他们黑白颜色不同,那么这个以$i$行为底的悬线的高度就是$height[i-1][j]+1$

    接下来我们考虑他的左右范围

    首先我们可以需要预处理出每个位置可以到的左右范围,比如说$lft[i][j]$就是从$(i,j)$开始往左满足左右相间可以一直到第几列。

    当我们要扩展一行的时候对于左边界只能取最右边的一个,对于右边界只能取最左边的。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<map>
     4 #include<set>
     5 #include<cstring>
     6 #include<algorithm>
     7 #include<vector>
     8 #include<cmath> 
     9 #include<stack>
    10 #include<queue>
    11 #include<iostream>
    12 
    13 #define inf 0x3f3f3f3f
    14 using namespace std;
    15 typedef long long LL;
    16 typedef pair<int, int> pr;
    17 
    18 int n, m;
    19 const int maxn = 2005; 
    20 int grid[maxn][maxn];
    21 int lft[maxn][maxn], rgt[maxn][maxn], height[maxn][maxn];
    22 
    23 int main()
    24 {
    25     scanf("%d%d", &n, &m);
    26     for(int i = 1; i <= n; i++){
    27         for(int j = 1; j <= m; j++){
    28             scanf("%d", &grid[i][j]);
    29             lft[i][j] = rgt[i][j] = j;
    30             height[i][j] = 1;
    31         }
    32     }
    33     
    34     for(int i = 1; i <= n; i++){
    35         for(int j = 2; j <= m; j++){
    36             if(grid[i][j] != grid[i][j - 1]){
    37                 lft[i][j] = lft[i][j - 1];
    38             }
    39         }
    40         for(int j = m - 1; j > 0; j--){
    41             if(grid[i][j] != grid[i][j + 1]){
    42                 rgt[i][j] = rgt[i][j + 1];
    43             }
    44         }
    45     }
    46     
    47     int anssqu = 0, ansrec = 0;
    48     for(int i = 1; i <= n; i++){
    49         for(int j = 1; j <= m; j++){
    50             if(i > 1 && grid[i][j] != grid[i - 1][j]){
    51                 lft[i][j] = max(lft[i][j], lft[i - 1][j]);
    52                 rgt[i][j] = min(rgt[i][j], rgt[i - 1][j]);
    53                 height[i][j] = height[i - 1][j] + 1;
    54             }
    55             int row = rgt[i][j] - lft[i][j] + 1;
    56             int col = min(row, height[i][j]);
    57             anssqu = max(anssqu, col * col);
    58             ansrec = max(ansrec, row * height[i][j]);
    59         }
    60     }
    61     
    62     printf("%d
    %d
    ", anssqu, ansrec);
    63 }
  • 相关阅读:
    linux cat 文件操作
    linux 如何显示一个文件的某几行(中间几行)
    dvm进程,linux进程,应用程序进程是否同一概念
    android-----JNI中的log打印
    push代码到github时,每次都要输入用户名和密码的问题
    linux下ndk编译命令行程序及配置
    Ubuntu16.04安装openjdk-7-jdk
    JNI——访问数组
    转:MyBatis学习总结(Mybatis总结精华文章)
    转:mybatis3中@SelectProvider的使用技巧
  • 原文地址:https://www.cnblogs.com/wyboooo/p/11106523.html
Copyright © 2011-2022 走看看