刚好在实际应用中碰到了类似问题,大致内容是需要求一个不规则区域的最大可用的矩形区域,当时的想法是首先获得不规则区域的外接矩形,矩形的某一条边与该区域的最长的一条边重叠,然后将外接矩形划分成很多个网格,判断每个网格是否处在区域中,在则置为1,不在为0,再求最大的都为1的矩形区域(与Maximal Rectangle问题类似)。
Maximal Square
利用动态规划的方法,用一个和matrix同样大小的数组假如是numofsq,来保存对于当前位置的以当前位置为右下角点的最大方形的边长。
对于中间的某一个位置(i,j),若该位置的值matrix[i][j]为0,则有numofsq[i][j]为0;若该位置的值为1,则判断该位置上、左上、左三个相邻元素的值,若不都为1,当前位置的numofsq[i][j]的值应置为1,如果都为1,那么当前位置可以和这三个相邻位置构成一个方形区域,同时上、左上、左三个对应的numofsq中分别存储着以它们为右下角点的方形大小,所以利用这个值就可以得出以当前位置为右下角点的方形大小。
第一行和第一列没有完整的上、左上、左三个位置,所以它的值只与当前位置的值相关。
matrix矩阵 numofsq矩阵 初始值 执行后的值
1 0 1 0 0 1 0 1 0 0 1 0 1 0 0
1 0 1 1 1 1 0 0 0 0 1 0 1 1 1
1 1 1 1 1 1 0 0 0 0 1 1 1 2 2
1 0 0 1 0 1 0 0 0 0 1 0 0 1 0
int maximalSquare(vector<vector<char>>& matrix) {
if (matrix.size() == 0 || matrix[0].size() == 0) return 0;
if (matrix.size() == 1) { //只有一行
for (int j = 0; j < matrix[0].size(); ++j) {
if (matrix[0][j] == '1') return 1;
}
return 0;
}
if (matrix[0].size() == 1) { //只有一列
for (int i = 0; i < matrix.size(); ++i) {
if (matrix[i][0] == '1') return 1;
}
return 0;
}
int row = matrix.size(), col = matrix[0].size();
vector<vector<int>> numofsq;
numofsq.resize(row);
for(int i = 0; i < row; ++i)
numofsq[i].resize(col);
int max = 0;
//初始化第一行和第一列
for (int i = 0; i < row; ++i) {
matrix[i][0] == '1' ? numofsq[i][0] = 1, max = 1 : numofsq[i][0] = 0;
}
for (int j = 1; j < col; ++j) {
matrix[0][j] == '1' ? numofsq[0][j] = 1, max = 1 : numofsq[0][j] = 0;
}
//计算中间部分
for (int i = 1; i < row; ++i) {
for (int j = 1; j < col; ++j) {
if (matrix[i][j] == '0')
numofsq[i][j] = 0;
else {
if (matrix[i - 1][j] > '0' && matrix[i - 1][j - 1] > '0' && matrix[i][j - 1] > '0') {
numofsq[i][j] = min(numofsq[i - 1][j], min(numofsq[i - 1][j - 1], numofsq[i][j - 1])) + 1;
}
else
numofsq[i][j] = 1;
if (max < numofsq[i][j])
max = numofsq[i][j];
}
}
}
return max*max;
}
Maximal Rectangle
待续…