m X n矩阵中的最大平方数

时间:2012-07-25 11:10:10

标签: algorithm

问题是:

  

给定一个包含1.s和0的M×N阶矩阵,你必须找到   可以形成的最大平方数。形成一个正方形   通过对包含1的相邻单元进行分组。最大平方是一个   并不完全包含在另一个广场内。最大二乘法   部分重叠的是单独计算。单位正方形   (边长= 1)也应计算在内。请注意,正方形是   填充,即它们不能含有0.s什么是最好的   算法?

示例:

对于以下4x5矩阵,输入将为:

示例输入和输出:

11001
11110
11011
11001

输出:

9

2 个答案:

答案 0 :(得分:3)

S(i,j)(i,j)右下角最大正方形的大小。 (我的索引从上到下,从左到右,从1开始。)整个S是整数的M x N矩阵。计算S是动态编程中非常经典的问题,已知其具有O(MN)时间复杂度。 (如果你不记得,这就是它的完成方式。假设A是输入矩阵。如果S(i,j) = 0设置A(i,j) = 0,如果{{1}则设置S(i,j) = min(S(i-1,j), S(i,j-1), S(i-1,j-1))+1如果您愿意,可以设置A(i,j) = 1。)

然后通过检查矩阵S(0,j) = S(i,0) = 0来提取最大方块。当且仅当S非零并且大于或等于(i,j)S(i,j)和{{1}时,S(i+1,j)右下角的正方形才是最大的}}。 (如果您愿意,请设置S(i,j+1)S(i+1,j+1)。)此步骤也需要O(MN)时间。

答案 1 :(得分:2)

可能的4x4正方形在(0,0)和(1,0)处具有顶部左侧。

可能的3x3正方形在(0,0),(1,0),(2,0),(0,1),(1,1),(2,1)处具有顶部左侧。

可能的2x2正方形在(0,0),(1,0),(2,0),(3,0),(0,1),(1,1),(2, 1),(3,1),(0,2),(1,2),(2,2),(3,2)。

可能的1x1正方形在所有坐标处都有顶部左侧。

所以算法可以如下:

从测试4x4开始,如果全部为1,则标记为属于4x4和增量计数。

然后测试3x3,如果全1并且未标记为属于4x4,则标记为属于3x3,并增加计数。

然后测试2x2,如果全1并且未标记为属于4x4或3x3,则标记为属于2x2,并增加计数。

然后测试1x1,如果是1并且根本没有标记,则增加计数。

返回计数。

如何标记单元格将特定于语言。例如用C我会使用一个位域。

编辑:为了好玩,我使用Bitset在Java中实现了这一点。

import java.util.BitSet; 

public class Program
    {
    // Right-shift bits by 'n' places
    private static BitSet RightShift(BitSet x, int n)
        {
        return x.get(n, Math.max(n, x.length()));
        }

    // Test square of dimension 'size' with top-left at position (h,w) for maximal-ness
    public static boolean IsMaximalSquare(BitSet [][] matrix, int h, int w, int size)
    {
        boolean isMaximal = true;
        for (int a = 0; a < size; a++)
        {
            for (int b = 0; b < size; b++)
            {
                BitSet x = matrix[h + a][w + b];
                if (!x.get(0))
                    return false;
                x = RightShift(x, size + 1);
                if (!x.isEmpty())
                    isMaximal = false;
            }
        }

        if (!isMaximal)
            return false;

        for (int a = 0; a < size; a++)
        {
            for (int b = 0; b < size; b++)
                matrix[h + a][w + b].set(size);
        }

        return true;
    }

    // Populate a 2d array of bitsets from string array
    public static BitSet [][] BuildMatrix(String rows[])
    {
        BitSet [][] matrix = new BitSet[4][5];

        for (int i = 0; i < 4; i++)
        {
            for (int j = 0; j < 5; j++)
            {
                matrix[i][j] = new BitSet(5);
                matrix[i][j].set(0, '1' == rows[i].charAt(j));
            }
        }
        return matrix;
    }

    // Return number of maximal squares from string representation of array
    public static int Solve(String rows[])
    {
        BitSet [][] matrix = BuildMatrix(rows);

        int count = 0;

        for (int size = 4; size > 0; size--) // test squares of size 4x4, 3x3, 2x2 and 1x1
        {
            for (int h = 0; h < 5 - size; h++) // iterate the rows
            {
                for (int w = 0; w < 6 - size; w++) // iterate the columns
                {
                    if (IsMaximalSquare(matrix, h, w, size))
                        count++;
                }
            }
        }

        return count;
    }

    public static void main(String[] args)
        {
        String rows1[] = {"11001","11110","11011","11001"}; // original question
        String rows2[] = {"11111","11111","11111","11111"}; // additional test case 1
        String rows3[] = {"00000","00000","00000","00000"}; // additional test case 2
        String rows4[] = {"11100","11111","11111","00111"}; // additional test case 3
        String rows5[] = {"11101","11111","11111","10111"}; // additional test case 4

        System.out.println(Solve(rows1));
        System.out.println(Solve(rows2));
        System.out.println(Solve(rows3));
        System.out.println(Solve(rows4));
        System.out.println(Solve(rows5));
        }
    }