Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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 <bits/stdc++.h>
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<pair<int, int> > painted)
{
    // Map to keep track for each cell that is
    // being affected by other blacks
    map<pair<int, int>, 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<int, int> 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<pair<int, int> > 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<Point> painted)
  {
 
    // Map to keep track for each cell that is
    // being affected by other blacks
    HashMap<Point, Integer> 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<Point, Integer> 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<Point> painted = new ArrayList<Point>();
 
    // 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


C#




// C# implementation of the above approach
using System;
using System.Collections.Generic;
 
class GFG{
     
// Function to check if a cell is safe or not
static bool 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<Tuple<int, int>> painted)
{
     
    // Map to keep track for each cell that is
    // being affected by other blacks
    Dictionary<Tuple<int,
                     int>, int> mp = new Dictionary<Tuple<int,
                                                          int>, int>(); 
                                                           
    for(int i = 0; i < painted.Count; ++i)
    {
        int x = painted[i].Item1;
        int y = painted[i].Item2;
         
        // 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))
                {
                     
                    Tuple<int,
                          int> temp = new Tuple<int,
                                                int>(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[temp] >= p * p)
                            continue
                        else
                            mp[temp]++;
                    }
                    else
                    {
                        mp[temp] = 1;
                    }
                }
            }
        }
    }
   
    // Answer array to store the answer.
    int[] ans = new int[p * p + 1]; 
    foreach(KeyValuePair<Tuple<int, int>, int> x in mp)
    {
        int cnt = x.Value;
        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;
    Console.WriteLine(ans[K]);
    return;
 
// Driver Code
static void Main()
{
    int H = 4, W = 5, N = 8, K = 4, P = 3;
    List<Tuple<int,
               int>> painted = new List<Tuple<int,
                                              int>>();
     
    // Initializing matrix
    painted.Add(new Tuple<int, int>(3, 1));
    painted.Add(new Tuple<int, int>(3, 2));
    painted.Add(new Tuple<int, int>(3, 4));
    painted.Add(new Tuple<int, int>(4, 4));
    painted.Add(new Tuple<int, int>(1, 5));
    painted.Add(new Tuple<int, int>(2, 3));
    painted.Add(new Tuple<int, int>(1, 1));
    painted.Add(new Tuple<int, int>(1, 4));
     
    CountSquares(H, W, N, K, P, painted);
}
}
 
// This code is contributed by divyeshrabadiya07


Javascript




<script>
 
// JavaScript implementation of the above approach
 
// Function to check if a cell is safe or not
function isSafe(x,y,h,w,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
function CountSquares(h,w,n,K,p,painted)
{
    // Map to keep track for each cell that is
    // being affected by other blacks
    let mp = new Map();
  
    for(let i = 0; i < painted.length; ++i)
    {
      let x = painted[i][0];
      let 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(let j = x - p + 1; j <= x; ++j)
      {
        for(let k = y - p + 1; k <= y; ++k)
        {
  
          // If the cell is safe
          if (isSafe(j, k, h, w, p))
          {
  
            let temp = [j, k].toString();
  
            // No need to increase the value
            // as there is no sense of paint
            // 2 blacks in one cell
            if (mp.has(temp))
            {
              if (mp.get(temp) >= p * p)
                continue;
              else
                mp.set(temp, mp.get(temp) + 1);
            }
            else
            {
              mp.set(temp, 1);
            }
          }
        }
      }
    }
  
    // Answer array to store the answer.
    let ans = new Array(p * p + 1);
    for(let i=0;i<ans.length;i++)
    {
        ans[i]=0;
    }
    for (let [key, value] of mp.entries())
    {
      let cnt = value;
      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
    let sum = 0;
    for(let 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
    let total = (h - p + 1) * (w - p + 1);
    ans[0] = total - sum;
    document.write(ans[K]+"<br>");
    return;
}
 
 // Driver code
let H = 4, W = 5, N = 8, K = 4, P = 3;
 
let painted = []
  
// Initializing matrix
painted.push([ 3, 1 ])
painted.push([ 3, 2 ])
painted.push([ 3, 4 ])
painted.push([ 4, 4 ])
painted.push([ 1, 5 ])
painted.push([ 2, 3 ])
painted.push([ 1, 1 ])
painted.push([ 1, 4 ])
  
CountSquares(H, W, N, K, P, painted)
 
 
// This code is contributed by unknown2108
 
</script>


 
 

Output: 

4

 

Time Complexity : O(N*p*p)
 



Last Updated : 30 Sep, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads