[USACO 6.1.2] A Rectangular Barn

题目大意

  给出一个R*C的矩形,里面有P个1*1的矩形是损坏的,选出一个最大的矩形并且不包含损环部分.

题解

  其实,在刘汝佳的书上曾经讲过类似的题目.具体大家自己找找看吧.

  设一个left和right数组.left[i][j],right[i][j]分别表示从(i,j)这个1*1的矩形(后文为方便表述称为格子)向左,右以这个格子最大高度(即向上延伸最长的长度)能够推进的最大长度.用语言表述可能有点乱,所以可以看下图.

  如上图,我们就这样计算出left和right数组后,逐个格子扫描一遍即可.

  时间复杂度O(N2),空间复杂度O(N2),但是left和right是可以滚动的.

代码

  

/*
TASK:rectbarn
LANG:C++
*/
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int MAXP = 30005;
const int MAXN = 3005;
const int INF = 0x7fffffff;

int r, c, p, cur, last, ans;
int len[MAXN], left[2][MAXN], right[2][MAXN];
bool g[MAXN][MAXN];

int main()
{
    freopen("rectbarn.in", "r", stdin);
    freopen("rectbarn.out", "w", stdout);
    scanf("%d%d%d", &r, &c, &p);
    memset(g, false, sizeof(g));
    for (int i = 0; i < p; ++i)
    {
        int x, y;
        scanf("%d%d", &x, &y);
        g[x][y] = true;
    }
    cur = ans = 0;
    memset(len, 0, sizeof(len));
    memset(left, 0x7f, sizeof(left));
    memset(right, 0x7f, sizeof(right));
    for (int i = 1; i <= r; ++i)
    {
        memset(left[cur], 0x7f, sizeof(left[cur]));
        memset(right[cur], 0x7f, sizeof(right[cur]));
        last = 0;
        for (int j = 1; j <= c; ++j)
            if (!g[i][j]) left[cur][j] = min(left[cur ^ 1][j], j - last - 1), len[j]++;
            else last = j, len[j] = 0;
        last = c + 1;
        for (int j = c; j >= 1; --j)
            if (!g[i][j]) right[cur][j] = min(right[cur ^ 1][j], last - j - 1);
            else last = j;
        for (int j = 1; j <= c; ++j)
            if (!g[i][j]) ans = max(ans, len[j] * (left[cur][j] + right[cur][j] + 1));
        cur ^= 1;
    }
    printf("%d
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/albert7xie/p/5730370.html