Open in App
Not now

# Find the number of p-sided squares in a grid with K blacks painted

• Difficulty Level : Medium
• Last Updated : 30 Sep, 2022

Given a grid of size H*W with all cells initially white. Given N pairs (i, j) in an array, for each pair, paint cell (i, j) with black colour. The task is to determine how many squares of size pÃ—p of the grid contains exactly K black cells, after N cells being painted.

Examples:

Input: H = 4, W = 5,
N = 8, K = 4, p = 3
arr=[ (3, 1), (3, 2), (3, 4), (4, 4),
(1, 5), (2, 3), (1, 1), (1, 4) ]
Output: 4
Cells that are being painted are shown in the figure below:
Here p = 3.
There are six subrectangles of size 3*3.
Two of them contain three black cells each,
and the remaining four contain four black cells each.

Input: H = 1, W = 1,
N = 1, K = 1, p = 1
arr=[ (1, 1) ]
Output: 1

Approach:

• First thing to observe is that one p*p sub-grid will be different from the other if their starting points are different.
• Second thing is that if the cell is painted black, it will contribute to p^2 different p*p sub-grids.
• For example, suppose cell [i, j] is painted black. Then it will contribute additional +1 to all the subgrids having starting point
[i-p+1][j-p+1] to [i, j].
• Since there can be at most N blacks, for each black cell do p*p iterations and update its contribution for each p*p sub-grids.
• Keep a map to keep track of answer for each cell of the grid.

Below is the implementation of the above approach:

## C++

 // C++ implementation of the above approach #include using namespace std;   // Function to check if a cell is safe or not bool isSafe(int x, int y, int h, int w, int p) {     if (x >= 1 and x <= h) {         if (y >= 1 and y <= w) {             if (x + p - 1 <= h) {                 if (y + p - 1 <= w) {                     return true;                 }             }         }     }     return false; }   // Function to print the number of p-sided squares // having k blacks void CountSquares(int h, int w, int n, int k,         int p, vector > painted) {     // Map to keep track for each cell that is     // being affected by other blacks     map, int> mp;     for (int i = 0; i < painted.size(); ++i) {         int x = painted[i].first;         int y = painted[i].second;           // For a particular row x and column y,         // it will affect all the cells starting         // from row = x-p+1 and column = y-p+1         // and ending at x, y         // hence there will be total         // of p^2 different cells         for (int j = x - p + 1; j <= x; ++j) {             for (int k = y - p + 1; k <= y; ++k) {                   // If the cell is safe                 if (isSafe(j, k, h, w, p)) {                     pair temp = { j, k };                       // No need to increase the value                     // as there is no sense of paint                     // 2 blacks in one cell                     if (mp[temp] >= p * p)                         continue;                     else                         mp[temp]++;                 }             }         }     }       // Answer array to store the answer.     int ans[p * p + 1];     memset(ans, 0, sizeof ans);     for (auto& x : mp) {         int cnt = x.second;         ans[cnt]++;     }       // sum variable to store sum for all the p*p sub     // grids painted with 1 black, 2 black,     // 3 black, ..., p^2 blacks,     // Since there is no meaning in painting p*p sub     // grid with p^2+1 or more blacks     int sum = 0;     for (int i = 1; i <= p * p; ++i)         sum = sum + ans[i];       // There will be total of     // (h-p+1) * (w-p+1), p*p sub grids     int total = (h - p + 1) * (w - p + 1);     ans[0] = total - sum;     cout << ans[k] << endl;     return; }   // Driver code int main() {     int H = 4, W = 5, N = 8, K = 4, P = 3;     vector > painted;       // Initializing matrix     painted.push_back({ 3, 1 });     painted.push_back({ 3, 2 });     painted.push_back({ 3, 4 });     painted.push_back({ 4, 4 });     painted.push_back({ 1, 5 });     painted.push_back({ 2, 3 });     painted.push_back({ 1, 1 });     painted.push_back({ 1, 4 });       CountSquares(H, W, N, K, P, painted);     return 0; }

## Java

 // Java implementation of the above approach import java.util.*; import java.awt.Point; class GFG {   // Function to check if a cell is safe or not   static boolean isSafe(int x, int y, int h,                         int w, int p)   {     if (x >= 1 && x <= h)     {       if (y >= 1 && y <= w)       {         if (x + p - 1 <= h)         {           if (y + p - 1 <= w)           {             return true;           }         }       }     }     return false;   }     // Function to print the number of p-sided squares    // having k blacks   static void CountSquares(int h, int w, int n, int K,                            int p, List painted)   {       // Map to keep track for each cell that is     // being affected by other blacks     HashMap mp = new HashMap<>();       for(int i = 0; i < painted.size(); ++i)     {       int x = painted.get(i).x;       int y = painted.get(i).y;         // For a particular row x and column y,        // it will affect all the cells starting       // from row = x-p+1 and column = y-p+1        // and ending at x, y       // hence there will be total        // of p^2 different cells       for(int j = x - p + 1; j <= x; ++j)       {         for(int k = y - p + 1; k <= y; ++k)         {             // If the cell is safe           if (isSafe(j, k, h, w, p))           {               Point temp = new Point(j, k);               // No need to increase the value             // as there is no sense of paint              // 2 blacks in one cell             if (mp.containsKey(temp))             {               if (mp.get(temp) >= p * p)                 continue;                else                 mp.put(temp, mp.get(temp) + 1);             }             else             {               mp.put(temp, 1);             }           }         }       }     }       // Answer array to store the answer.     int[] ans = new int[p * p + 1];      for (Map.Entry x : mp.entrySet())     {       int cnt = x.getValue();       ans[cnt]++;     }       // sum variable to store sum for all the p*p sub     // grids painted with 1 black, 2 black,      // 3 black, ..., p^2 blacks,     // Since there is no meaning in painting p*p sub     // grid with p^2+1 or more blacks     int sum = 0;      for(int i = 1; i <= p * p; ++i)       sum = sum + ans[i];       // There will be total of      // (h-p+1) * (w-p+1), p*p sub grids     int total = (h - p + 1) * (w - p + 1);      ans[0] = total - sum;     System.out.println(ans[K]);     return;   }       // Driver code   public static void main(String[] args)   {     int H = 4, W = 5, N = 8, K = 4, P = 3;     List painted = new ArrayList();       // Initializing matrix     painted.add(new Point(3, 1));     painted.add(new Point(3, 2));     painted.add(new Point(3, 4));     painted.add(new Point(4, 4));     painted.add(new Point(1, 5));     painted.add(new Point(2, 3));     painted.add(new Point(1, 1));     painted.add(new Point(1, 4));       CountSquares(H, W, N, K, P, painted);   } }   // This code is contributed by divyesh072019

## Python3

 # Python3 implementation of the above approach   # Function to check if a cell is safe or not def isSafe(x, y, h, w, p):     if (x >= 1 and x <= h):         if (y >= 1 and y <= w):             if (x + p - 1 <= h):                 if (y + p - 1 <= w):                     return True     return False   # Function to print the number of p-sided squares # having k blacks def CountSquares(h, w, n, k, p, painted):           # Map to keep track for each cell that is     # being affected by other blacks     mp = dict()     for i in range(len(painted)):         x = painted[i][0]         y = painted[i][1]           # For a particular row x and column y,         # it will affect all the cells starting         # from row = x-p+1 and column = y-p+1         # and ending at x, y         # hence there will be total         # of p^2 different cells         for j in range(x - p + 1, x + 1):             for k in range(y - p + 1, y + 1):                   # If the cell is safe                 if (isSafe(j, k, h, w, p)):                     temp = (j, k)                       # No need to increase the value                     # as there is no sense of pa                     # 2 blacks in one cell                     if (temp in mp.keys() and mp[temp] >= p * p):                         continue                     else:                         mp[temp] = mp.get(temp, 0) + 1       # Answer array to store the answer.     ans = [0 for i in range(p * p + 1)]           # memset(ans, 0, sizeof ans)     for x in mp:         cnt = mp[x]         ans[cnt] += 1       # Sum variable to store Sum for all the p*p sub     # grids painted with 1 black, 2 black,     # 3 black, ..., p^2 blacks,     # Since there is no meaning in painting p*p sub     # grid with p^2+1 or more blacks     Sum = 0     for i in range(1, p * p + 1):         Sum = Sum + ans[i]       # There will be total of     # (h-p+1) * (w-p+1), p*p sub grids     total = (h - p + 1) * (w - p + 1)     ans[0] = total - Sum     print(ans[k])     return   # Driver code H = 4 W = 5 N = 8 K = 4 P = 3 painted = []   # Initializing matrix painted.append([ 3, 1 ]) painted.append([ 3, 2 ]) painted.append([ 3, 4 ]) painted.append([ 4, 4 ]) painted.append([ 1, 5 ]) painted.append([ 2, 3 ]) painted.append([ 1, 1 ]) painted.append([ 1, 4 ])   CountSquares(H, W, N, K, P, painted)       # This code is contributed by Mohit Kumar

## Javascript



Output:

4

Time Complexity : O(N*p*p)

My Personal Notes arrow_drop_up
Related Articles