在方阵中,每个单元格为黑色或白色。设计算法以找到最大子方块,使得所有4个边界都是黑色的

时间:2011-11-11 17:01:53

标签: c++ c performance algorithm data-structures

给定方阵,每个单元格为黑色或白色。设计算法以找到最大子方块,使得所有4个边界都是黑色的。

我有O(n ^ 2)算法:

从左到右扫描每列,对于每列中的每个单元格,扫描每一行以查找带有后边框的最大子正方形。

有更好的解决方案吗?

感谢

4 个答案:

答案 0 :(得分:5)

O(n ^ 2)是可能的。我想这是最佳的,因为你有n ^ 2个细胞。

请注意,任何方块的左上角和右下角都位于同一对角线上。

现在如果我们可以在O(n)时间内处理每个对角线,我们将有一个O(n ^ 2)时间算法。

假设我们有一个左上角的候选人。我们可以计算它下面和它右边的连续黑色单元格的数量,并将它们中的最小值称为T.

对于右下角的候选者,我们可以计算左边的连续黑色单元格的数量,并且在顶部并取两者中的最小值,称之为B.

一旦我们得到两个数字T和B,我们可以判断给定的左上角,右下角候选者是否实际上给了我们一个带有所有黑色边框的正方形。

现在可以通过在整个矩阵中进行四次遍历,在O(n ^ 2)时间内为每个单元格计算这两个数字(如何?)。

所以让我们假设已经完成了。

现在考虑一个对角线。我们的目标是在O(n)时间沿该对角线找到左上,右下对。

我们假设我们在数组T [1 ... m]中计算了T,其中m是对角线的长度。同样,我们有一个数组B [1 ... m]。 T [1]对应于对角线的左上端,T [m]对应于右下角。与B类似。

现在我们按如下方式处理对角线,对于每个左上角候选者i,我们尝试找到一个右下角候选j,它将给出最大的方形。请注意,j> = i。还要注意,如果(i,j)是候选者,则(i',j)不是,其中i'和gt;岛

请注意,如果T[i] >= j-i+1B[j] >= j-i+1,则i和j形成正方形。

即。 T[i] +i - 1 >= jB[j] -j - 1 >= -i

因此我们形成了新的数组TL[k] = T[k] + k -1BR[k] = B[k] -k - 1

所以给定两个新的数组TL和BR,以及一个i,我们需要回答以下问题:

  

最大的j是什么,TL [i]> = j和BR [j]> = -i?

现在假设我们能够处理BR以进行范围最大查询(可以在O(m)时间内完成)。

现在给定TL [i],在[i,TL [i]]范围内,我们找到BR的最大值,比如BR [j1]。

现在,如果BR [j1]> = -i,我们在[j1,TL [i]]范围内找到BR的最大值,并以此方式继续。

一旦找到(TL [i],BR [j])候选者,我们可以忽略未来i的数组BR [1 ... j]。

这允许我们在O(n)时间内处理每个对角线,给出一个O(n ^ 2)总算法。

我遗漏了很多细节并给出了草图,因为它已经太长了。请随意修改此内容。

呼。

答案 1 :(得分:0)

C ++代码:

#include<iostream>
using namespace std;

int min(int a,int b,int c)
{
    int min = a;
    if(min > b)
        min = b;
    if(min > c)
        min = c;
    return min;
}

int main()
{
    const int size  = 5;
    char a[size][size] = { {'b','b','b','b','w'},{'b','b','b','b','b'},{'b','b','b','b','b'},{'b','b','w','b','b'},{'b','w','w','b','b'} };
    int arr[size+1][size+1];
    // First row and First column of arr is zero.
    for(int i=0;i<size+1;i++)
    {
        arr[0][i] = 0;
        arr[i][0] = 0;
    }
    int answer = 0;
    for(int i=0;i<size;i++)
    {
        for(int j=0;j<size;j++)
        {
            if(a[i][j] == 'w')
                arr[i+1][j+1] = 0;
            if(a[i][j] == 'b')
            {
                int minimum = min(arr[i][i],arr[i+1][j],arr[i][j+1]);
                arr[i+1][j+1] = minimum + 1;
                if( arr[i+1][j+1] > answer)
                    answer = arr[i+1][j+1];
            }
        }
    }
    for(int i=0;i<size+1;i++)
    {
        for(int j=0;j<size+1;j++)
        {
            cout<<arr[i][j]<<"\t";
        }
        cout<<endl;
    }
    cout<<answer<<endl;
    return 0;
}

答案 2 :(得分:0)

/* In a square matrix, where each cell is black or white. 
 * Design an algorithm to find the max sub-square such that all 4 borders are black. The right Java implementation based on a previous post. 
 */
public int maxSubsquare(boolean[][] M){
    int n = M.length; 
    maxsize=0; 
    checkDiag(M, 0, 0, n); 
    for (int i=1; i<n; i++){
        checkDiag(M, i, 0, n); 
        checkDiag(M, 0, i, n); 
    }
    return maxsize; 
}
int maxsize; 
void checkDiag(boolean[][] M, int i, int j, int n){
    if (i>=n-maxsize || j>=n-maxsize) return; 
    int step = 0; 
    while (step<(n-Math.max(i, j))&& M[i][j+step]&&M[i+step][j]){
        int s = step; 
        while (s>0){
            if (M[i+s][j+step]&&M[i+step][j+s]) s--; 
            else break; 
        }
        if (s==0) 
            maxsize = Math.max(maxsize, step+1); 
        step++; 
    }
    if (step==0) checkDiag(M, i+step+1, j+step+1, n); 
    else checkDiag(M, i+step, j+step, n); 
}

答案 3 :(得分:0)

我不知道为什么你可以得到一个O(n ^ 2)算法。在数学上,这是不可能的。 我们假设你有一个NxN矩阵。你需要检查: 1. 1矩阵大小:NxN, 2. 2 * 2矩阵大小:(N-1)x(N-1), 3. 3 * 3矩阵大小:(N-2)x(N-2), ....

总共需要检查:1 + 2 ^ 2 + 3 ^ 2 + ... + N ^ 2 = N(N + 1)(2N + 1)/ 6。 所以任何算法都不能比O(N ^ 3)

做得更好