给定一个大小为NXM的二进制矩阵,任务是回答以下类型的Q查询;
Query(a, b): Find the number of sub matrices of size a X a with each of its element consisting of the Binary Number b.
我们基本上需要找到给定大小的全 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] 可以定义为:
1) If i = 0 OR j = 0 In this Case, dp[i][j] = 1, because only 1 X 1 is the only square matrix that can be formed at 0th row or 0th column whose all elements are equal
to m[i][j] and the last element is (i, 0) or (0, j).
2) If m[i][j] = m[i-1][j] = m[i][j-1] = m[i-1][j-1] dp[i][j] = min(dp[i][j-1], dp[i-1][j], dp[i-1][j-1]) + 1, if the binary number at m[i][j] is equal to the binary number at m[i-1][j], m[i-1][j-1] and m[i][j-1]. Because if the current binary number is equal to all the three binary numbers it will form a 2 X 2 square sub-matrix where all the elements are equal. Also, it will contribute 1 more row and column to the square matrix with all equal element at position m[i-1][j], m[i-1][j-1] and m[i][j-1].
dp[i][j] = 1, if above conditions do not meet because a single cell will always contribute a 1 X 1 sub matrix.
现在,遍历二维 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 现场工作专业课程和学生竞争性编程现场课程。