📌  相关文章
📜  查询给定大小的二进制子矩阵的数量

📅  最后修改于: 2021-09-22 09:44:42             🧑  作者: Mango

给定一个大小为NXM的二进制矩阵,任务是回答以下类型的Q查询;

我们基本上需要找到给定大小的全 1 或全 0 的子矩阵。

例子:

Input : N = 5, M = 4
        m[][] = { { 0, 0, 1, 1 },
                  { 0, 0, 1, 0 },
                  { 0, 1, 1, 1 },
                  { 1, 1, 1, 1 },
                  { 0, 1, 1, 1 }
                }
        Q = 2
        Query 1 : a = 2, b = 1
        Query 2 : a = 2, b = 0 
Output : 4 1

Explanation:
For Query 1,
0011  0011  0011  0011
0010  0010  0010  0010
0111  0111  0111  0111
1111  1111  1111  1111
0111  0111  0111  0111

For Query 2,
0011
0010
0111
1111
0111

Input : N = 5, M = 4
        m[][] = { { 0, 0, 1, 1 },
                  { 0, 0, 1, 0 },
                  { 0, 1, 1, 1 },
                  { 1, 1, 1, 1 },
                  { 0, 1, 1, 1 }
                }

        Q = 1
        Query 1 : a = 3, b = 1
Output : 1

这个想法是使用动态规划来解决问题。首先声明一个二维数组dp[][] ,其中 dp[i][j] 处的值(比如 K)表示可以形成的最大方形子矩阵 (KXK) 的大小,其所有元素都等于 m[ i][j] 和 (i, j) 是子矩阵的最后一个元素(东南)。现在,dp[i][j] 可以定义为:

现在,遍历二维 dp[][] 数组并计算所有不同值的频率(元素 0 为 freq0[],元素 1 为 freq1[]),即 0 和 1 的不同大小的方形子矩阵.

观察,要计算大小为 YXY 的方形子矩阵,则 Y+1 X Y+1 也将贡献 1 个计数。假设我们需要计算 2 X 2 矩阵和 dp[][]=

...22
...23

这里,2 的频率是 3,但观察 dp[i][j] = 3 的元素也贡献了一个 2 X 2 方阵子矩阵。
因此,找到 freq0[] 和 freq1[] 的频率的累积和。

下面是这个方法的实现:

C++
// CPP Program to answer queries on number of
// submatrix of given size
#include 
using namespace std;
 
#define MAX 100
#define N 5
#define M 4
 
// Return the minimum of three numbers
int min(int a, int b, int c)
{
    return min(a, min(b, c));
}
 
// Solve each query on matrix
void solveQuery(int n, int m, int mat[N][M], int q,
                             int a[], int binary[])
{
    int dp[n][m], max = 1;
 
    // For each of the cell.
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
 
            // finding submatrix size of oth row
            // and column.
            if (i == 0 || j == 0)
                dp[i][j] = 1;
 
            // intermediate cells.
            else if ((mat[i][j] == mat[i - 1][j]) &&
                     (mat[i][j] == mat[i][j - 1]) &&
                     (mat[i][j] == mat[i - 1][j - 1])) {
 
                dp[i][j] = min(dp[i - 1][j], dp[i - 1][j - 1],
                               dp[i][j - 1])
                           + 1;
 
                if (max < dp[i][j])
                    max = dp[i][j];
            }
 
            else
                dp[i][j] = 1;
        }
    }
 
    int freq0[MAX] = { 0 }, freq1[MAX] = { 0 };
 
    // Find frequency of each distinct size
    // for 0s and 1s.
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (mat[i][j] == 0)
                freq0[dp[i][j]]++;
            else
                freq1[dp[i][j]]++;
        }
    }
 
    // Find the Cumulative Sum.
    for (int i = max - 1; i >= 0; i--) {
        freq0[i] += freq0[i + 1];
        freq1[i] += freq1[i + 1];
    }
 
    // Output the answer for each query
    for (int i = 0; i < q; i++) {
        if (binary[i] == 0)
            cout << freq0[a[i]] << endl;
        else
            cout << freq1[a[i]] << endl;
    }
}
 
// Driver Program
int main()
{
    int n = 5, m = 4;
    int mat[N][M] = {
        { 0, 0, 1, 1 },
        { 0, 0, 1, 0 },
        { 0, 1, 1, 1 },
        { 1, 1, 1, 1 },
        { 0, 1, 1, 1 }
    };
    int q = 2;
    int a[] = { 2, 2 };
    int binary[] = { 1, 0 };
 
    solveQuery(n, m, mat, q, a, binary);
 
    return 0;
}


Java
// Java Program to answer queries on number of
// submatrix of given size
import java.io.*;
 
class GFG {
 
    static int MAX = 100;
    static int N = 5;
    static int M = 4;
     
    // Return the minimum of three numbers
    static int min(int a, int b, int c)
    {
        return Math.min(a, Math.min(b, c));
    }
     
    // Solve each query on matrix
    static void solveQuery(int n, int m, int mat[][],
                        int q, int a[], int binary[])
    {
        int dp[][] = new int[n][m];
        int max = 1;
     
        // For each of the cell.
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
     
                // finding submatrix size of oth row
                // and column.
                if (i == 0 || j == 0)
                    dp[i][j] = 1;
     
                // intermediate cells.
                else if ((mat[i][j] == mat[i - 1][j])
                      && (mat[i][j] == mat[i][j - 1])
                 && (mat[i][j] == mat[i - 1][j - 1]))
                 {
     
                    dp[i][j] = min(dp[i - 1][j],
                               dp[i - 1][j - 1],
                                dp[i][j - 1]) + 1;
     
                    if (max < dp[i][j])
                        max = dp[i][j];
                }
     
                else
                    dp[i][j] = 1;
            }
        }
     
        int freq0[] = new int[MAX];
        int freq1[] = new int[MAX];
     
        // Find frequency of each distinct size
        // for 0s and 1s.
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (mat[i][j] == 0)
                    freq0[dp[i][j]]++;
                else
                    freq1[dp[i][j]]++;
            }
        }
     
        // Find the Cumulative Sum.
        for (int i = max - 1; i >= 0; i--) {
            freq0[i] += freq0[i + 1];
            freq1[i] += freq1[i + 1];
        }
     
        // Output the answer for each query
        for (int i = 0; i < q; i++) {
            if (binary[i] == 0)
                System.out.println( freq0[a[i]]);
            else
                System.out.println( freq1[a[i]]);
        }
    }
     
    // Driver Program
 
    public static void main (String[] args)
    {
        int n = 5, m = 4;
        int mat[][] = { { 0, 0, 1, 1 },
                        { 0, 0, 1, 0 },
                        { 0, 1, 1, 1 },
                        { 1, 1, 1, 1 },
                        { 0, 1, 1, 1 } };
        int q = 2;
        int a[] = { 2, 2 };
        int binary[] = { 1, 0 };
     
        solveQuery(n, m, mat, q, a, binary);
    }
}
 
// This code is contributed by anuj_67.


Python3
# Python 3 Program to answer queries on number of
# submatrix of given size
MAX = 100
N = 5
M = 4
 
# Solve each query on matrix
def solveQuery(n, m, mat, q,
               a, binary):
 
    dp = [[0 for x in range(m)]for y in range(n)]
    max = 1
 
    # For each of the cell.
    for i in range(n):
        for j in range(m):
 
            # finding submatrix size of oth row
            # and column.
            if (i == 0 or j == 0):
                dp[i][j] = 1
 
            # intermediate cells.
            elif ((mat[i][j] == mat[i - 1][j]) and
                  (mat[i][j] == mat[i][j - 1]) and
                  (mat[i][j] == mat[i - 1][j - 1])):
 
                dp[i][j] = (min(dp[i - 1][j], min(dp[i - 1][j - 1],
                                                  dp[i][j - 1])) + 1)
 
                if (max < dp[i][j]):
                    max = dp[i][j]
 
            else:
                dp[i][j] = 1
 
    freq0 = [0] * MAX
    freq1 = [0] * MAX
 
    # Find frequency of each distinct size
    # for 0s and 1s.
    for i in range(n):
        for j in range(m):
            if (mat[i][j] == 0):
                freq0[dp[i][j]] += 1
            else:
                freq1[dp[i][j]] += 1
 
    # Find the Cumulative Sum.
    for i in range(max - 1, -1, -1):
        freq0[i] += freq0[i + 1]
        freq1[i] += freq1[i + 1]
 
    # Output the answer for each query
    for i in range(q):
        if (binary[i] == 0):
            print(freq0[a[i]])
        else:
            print(freq1[a[i]])
 
 
# Driver Program
if __name__ == "__main__":
 
    n = 5
    m = 4
    mat = [
        [0, 0, 1, 1],
        [0, 0, 1, 0],
        [0, 1, 1, 1],
        [1, 1, 1, 1],
        [0, 1, 1, 1]
    ]
    q = 2
    a = [2, 2]
    binary = [1, 0]
 
    solveQuery(n, m, mat, q, a, binary)
 
    # This code is contributed by ukasp.


C#
// C# Program to answer
// queries on number of
// submatrix of given size
using System;
 
class GFG
{
    static int MAX = 100;
    // static int N = 5;
    // static int M = 4;
     
    // Return the minimum
    // of three numbers
    static int min(int a,
                   int b,
                   int c)
    {
        return Math.Min(a, Math.Min(b, c));
    }
     
    // Solve each query on matrix
    static void solveQuery(int n, int m,
                           int [,]mat, int q,
                           int []a, int []binary)
    {
        int [,]dp = new int[n, m];
        int max = 1;
     
        // For each of the cell.
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
     
                // finding submatrix size
                // of oth row and column.
                if (i == 0 || j == 0)
                    dp[i, j] = 1;
     
                // intermediate cells.
                else if ((mat[i, j] == mat[i - 1, j]) &&
                         (mat[i, j] == mat[i, j - 1]) &&
                         (mat[i, j] == mat[i - 1, j - 1]))
                {
     
                    dp[i, j] = min(dp[i - 1, j],
                                   dp[i - 1, j - 1],
                                   dp[i, j - 1]) + 1;
     
                    if (max < dp[i, j])
                        max = dp[i, j];
                }
     
                else
                    dp[i, j] = 1;
            }
        }
     
        int []freq0 = new int[MAX];
        int []freq1 = new int[MAX];
     
        // Find frequency of each
        // distinct size for 0s and 1s.
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                if (mat[i, j] == 0)
                    freq0[dp[i, j]]++;
                else
                    freq1[dp[i, j]]++;
            }
        }
     
        // Find the Cumulative Sum.
        for (int i = max - 1; i >= 0; i--)
        {
            freq0[i] += freq0[i + 1];
            freq1[i] += freq1[i + 1];
        }
     
        // Output the answer
        // for each query
        for (int i = 0; i < q; i++)
        {
            if (binary[i] == 0)
                Console.WriteLine(freq0[a[i]]);
            else
                Console.WriteLine(freq1[a[i]]);
        }
    }
     
    // Driver Code
    public static void Main ()
    {
        int n = 5, m = 4;
        int [,]mat = {{0, 0, 1, 1},
                      {0, 0, 1, 0},
                      {0, 1, 1, 1},
                      {1, 1, 1, 1},
                      {0, 1, 1, 1}};
        int q = 2;
        int []a = {2, 2};
        int []binary = {1, 0};
     
        solveQuery(n, m, mat,
                   q, a, binary);
    }
}
 
// This code is contributed by anuj_67.


Javascript


输出:
4
1

上述算法的时间复杂度为O(n * m)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程