考点
题解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e3 + 50; ll ans; char c[maxn][maxn]; int n, m, top, st[maxn], h[maxn], l[maxn], r[maxn];
int main() { cin >> n >> m; for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) { cin >> c[i][j]; } } for (int i = 1; i <= n; ++i) { for (int j = 1; j <= m; ++j) h[j] = c[i][j] == '.' ? h[j] + 1 : 0; top = 0; for (int j = 1; j <= m; ++j) { while (top && h[st[top]] > h[j]) r[st[top--]] = j; st[++top] = j; } while (top) r[st[top--]] = m + 1; top = 0; for (int j = m; j >= 1; --j) { while (top && h[st[top]] >= h[j]) l[st[top--]] = j; st[++top] = j; } while (top) l[st[top--]] = 0; for (int j = 1; j <= m; ++j) ans += 1ll * h[j] * (j - l[j]) * (r[j] - j); } cout << ans; return 0; }
|
思路
本题是P4147的升级版,请先掌握该题;题目问有多少种剪矩形的办法。
根据悬线法可知,一个最大矩形可以由中线切开,组成的可能性 = 左半部分的可能性 * 右半部分的可能性
本题实际上就是求每个悬线向左和向右的最大扩展距离罢了~
但是要注意不重不漏哟,如下图所示:
明白了这些后,再看《深进》就懂啦~