洛谷P1169 棋盘制作【悬线法】【区间dp】

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

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

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

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

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

洛谷P1169 棋盘制作【悬线法】【区间dp】

对于这道题来说,如果$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\n%d\n", anssqu, ansrec);
63 }

 

上一篇:修改CentOS7网卡名字


下一篇:docker容器之间网络是如何通信的?