洛谷P1169 棋盤製做【懸線法】【區間dp】

題目https://www.luogu.org/problemnew/show/P1169ios

題意:n*m的黑白格子,找到面積最大的黑白相間的正方形和矩形。spa

思路:傳說中的懸線法!用下面這張圖說明一下。code

懸線法通常是用來求一個沒有障礙點的最大子矩陣的。想象從上面垂下來好多的懸線,這些懸線被一個底所限制,而且能夠左右移動可是也有範圍限制。blog

如今某條懸線能夠移動到的面積就是他能知足的子矩形的面積。好比咱們已經處理好了$i-1$行,如今考慮$(i,j)$get

對於這道題來講,若是$grid[i][j]!=grid[i-1][j]$就說明他們黑白顏色不一樣,那麼這個以$i$行爲底的懸線的高度就是$height[i-1][j]+1$string

接下來咱們考慮他的左右範圍it

首先咱們能夠須要預處理出每一個位置能夠到的左右範圍,好比說$lft[i][j]$就是從$(i,j)$開始往左知足左右相間能夠一直到第幾列。io

當咱們要擴展一行的時候對於左邊界只能取最右邊的一個,對於右邊界只能取最左邊的。class

 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 }
相關文章
相關標籤/搜索