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

📅  最后修改于: 2021-04-24 21:09:37             🧑  作者: 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

想法是使用动态编程来解决该问题。首先声明2D数组dp [] [] ,其中dp [i] [j]的值(例如K)表示可以形成的最大平方子矩阵(KXK)的大小,其所有元素均等于m [ i] [j]和(i,j)是子矩阵的最后一个元素(东南)。现在,可以将dp [i] [j]定义为:

现在,遍历二维dp [] []数组并计算所有不同值的频率(元素0的freq0 [],元素1的freq1 []),即0s和1s的正方形子矩阵的不同大小的频率。
观察到,要对大小为YXY的平方子矩阵进行计数,则Y + 1 X Y + 1也将贡献1个计数。假设我们需要计算2 X 2矩阵和dp [] [] =

...22
...23

在这里,二的频率为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.


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.


输出:
4
1

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