题目大意
给出一个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; }