Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing all ones and return its area.
题意:给出一个矩形,里面填充'0'和'1',找出完全由'1'组成的最大子矩形的面积。
分析:我是用dp做这道题的。用row[i][j]和col[i][j]分别记录以点(i,j)为右下角的全1子矩形的行数和列数。用right[i][j]和down[i][j]记录以(i,j)为结尾的从左到右连续1个数、从上到下连续1个数。
依次遍历每个点(i,j),考虑点(i-1,j)和(i,j-1)。
对于点(i-1,j),考虑(row[i-1][j]+1)*col[i-1][j]是否小于单行连续1个数right[i][j],若小于,记录以(i,j)为右下角的最大矩形为这个单行连1;否则,记录为(i-1,j)对应矩形加当前行,列数为min(col[i-1][j],right[i][j])。
对于点(i-1,j),考虑row[i][j-1]*(col[i][j-1]+1)是否小于单列连续1个数down[i][j],若小于,记录以(i,j)为右下角的最大矩形为这个单列连1;否则,记录为(i,j-1)对应矩形加当前列,行数为min(row[i][j-1],down[i][j])。
选上述两个结果的较大矩形,作为(i,j)的结果。
记录所有点中的最大矩形面积,即为结果。
代码:
class Solution {
public:
int maximalRectangle(vector<vector<char> > &matrix) {
int n = matrix.size();
if(n==0) return 0;
int m = matrix[0].size();
if(m==0) return 0;
int **row = new int*[n+1];
int **col = new int*[n+1];
int **right = new int*[n+1];
int **down = new int*[n+1];
for(int i=0; i<=n; i++)
{
row[i] = new int[m+1];
col[i] = new int[m+1];
right[i] = new int[m+1];
down[i] = new int[m+1];
memset(row[i],0,sizeof(int)*(m+1));
memset(col[i],0,sizeof(int)*(m+1));
memset(right[i],0,sizeof(int)*(m+1));
memset(down[i],0,sizeof(int)*(m+1));
}
for(int i=0; i<n; i++)
{
for(int j=0; j<m; j++)
{
if(matrix[i][j]=='0') right[i+1][j+1]=0;
else right[i+1][j+1]=right[i+1][j]+1;
}
}
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
if(matrix[j][i]=='0') down[j+1][i+1]=0;
else down[j+1][i+1]=down[j][i+1]+1;
}
}
int ans = 0;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
if(matrix[i-1][j-1]=='1')
{
row[i][j]=1;
col[i][j]=1;
int r1,c1,r2,c2;
if(right[i][j]>(row[i-1][j]+1)*col[i-1][j])
{
r1 = 1;
c1 = right[i][j];
}
else
{
r1 = row[i-1][j]+1;
c1 = min(col[i-1][j],right[i][j]);
}
if(down[i][j]>row[i][j-1]*(col[i][j-1]+1))
{
r2 = down[i][j];
c2 = 1;
}
else
{
r2 = min(row[i][j-1],down[i][j]);
c2 = col[i][j-1]+1;
}
if(r1*c1>r2*c2)
{
row[i][j] = r1;
col[i][j] = c1;
}
else
{
row[i][j] = r2;
col[i][j] = c2;
}
if(row[i][j]*col[i][j]>ans)
ans = row[i][j]*col[i][j];
}
}
}
return ans;
}
};