Petrozavodsk Winter Camp, Warsaw U, 2014, A The Carpet

一个地图上有若干障碍,问允许出现一个障碍的最大子矩形为多大?

最大子矩形改编

 

#include<bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (int i = int(j); i <= int(k); ++ i)
#define dwn(i, j, k) for (int i = int(j); i >= int(k); -- i)
const int N = 2007; 
int n, m, l[N][2], r[N][2], h[N][2];
char s[N][N];


int main() {
    scanf("%d%d", &n, &m);
    rep(i, 1, n) scanf("%s", s[i] + 1);
    int ans = 0;
    // 枚举障碍不在悬线上
    // l[j][0]表示最左扩展(不能包含障碍),l[j][1]表示最右扩展(能包含障碍)
    rep(j, 1, m) l[j][0] = l[j][1] = j, r[j][0] = r[j][1] = m + 1 - j;
    rep(i, 1, n) {
        int lb0 = 0, lb1 = 0;
        rep(j, 1, m) {
            if (s[i][j] == '.') {
                h[j][0] ++; ans = max(ans, h[j][0]);
                l[j][1] = max(min(l[j][1], j - lb0), min(l[j][0], j - lb1));
                l[j][0] = min(l[j][0], j - lb0);
            }
            else {
                lb1 = lb0;
                lb0 = j;
                l[j][0] = l[j][1] = j;
                h[j][0] = 0;
            }
        }
        int rb0 = m + 1, rb1 = m + 1;
        dwn(j, m, 1) {
            if (s[i][j] == '.') {
                r[j][1] = max(min(r[j][1], rb0 - j), min(r[j][0], rb1 - j));
                r[j][0] = min(r[j][0], rb0 - j);
                ans = max(ans, (l[j][0] + r[j][0] - 1) * h[j][0]);
                ans = max(ans, (l[j][0] + r[j][1] - 1) * h[j][0]);
                ans = max(ans, (l[j][1] + r[j][0] - 1) * h[j][0]);
            }
            else {
                rb1 = rb0;
                rb0 = j;
                r[j][0] = r[j][1] = m + 1 - j;
            }
        }
    }
    // 枚举障碍在悬线上
    // 这时候的l[j][0]表示没有障碍的悬线最左扩展,l[j][1]表示有障碍的悬线最左扩展
    rep(j, 1, m) l[j][0] = l[j][1] = j, r[j][0] = r[j][1] = m + 1 - j, h[j][0] = h[j][1] = 0;
    rep(i, 1, n) {
        int lb = 0;
        rep(j, 1, m) {
            if (s[i][j] == '.') {
                h[j][0] ++; h[j][1] ++;
                l[j][0] = min(l[j][0], j - lb);
                l[j][1] = min(l[j][1], j - lb);
            }
            else {
                l[j][1] = min(l[j][0], j - lb);
                h[j][1] = h[j][0] + 1; h[j][0] = 0;
                l[j][0] = j;
                lb = j;
            }
        }
        int rb = m + 1;
        dwn(j, m, 1) {
            if (s[i][j] == '.') {
                r[j][0] = min(r[j][0], rb - j);
                r[j][1] = min(r[j][1], rb - j);
            }
            else {
                r[j][1] = min(r[j][0], rb - j);
                r[j][0] = m + 1 - j;
                rb = j;
            }
        }
        rep(j, 1, m) {
            ans = max(ans, h[j][1] * (l[j][1] + r[j][1] - 1));
        }
    }   
    cout << ans << '\n';
}
/*
4 5 
#.#.. 
....# 
..#.. 
....#
*/

 

posted @ 2019-04-11 10:53  zd11024  阅读(220)  评论(0编辑  收藏  举报