House should not have a house on its left cell
House should not have a house on its right cell
House should not have a house on its upper-left cell
House should not have a house on its upper-right cell
Input :
M = 3 , N = 5
Grid :
. . . T .
. T . . .
T . . T .
In the example above, the maximum number of houses that be built is 8.
The first line of input contains an integer ‘T’ denoting the number of test cases to run. Then ‘T’ test cases follow:
The first line in each test case contains two space-separated positive integers ‘M’ and ‘N’, where 'M’ is the number of rows and ‘N’ is the number of columns in the grid.
The next ‘M’ lines contain a string of length ‘N’ containing ‘.’ or ‘T’ representing empty space or a Tree, respectively.
For each test case, print an integer denoting the maximum number of houses that can build following the conditions stated above.
Output for every test case will be printed in a separate line.
You don’t need to print anything; It has already been taken care of. Just implement the given function.
1 <= T <= 5
1 <= N <= 8
1 <= M <= 8
‘TOWN’ = { “.”,"T"}
Where 'TOWN’ denotes the 2-D grid represents whether a cell is empty or not.
Time limit: 1 sec
First of all, we should know why we are doing bitmasking? Below is the explanation:
Let’s now discuss the approach:
Below are the functionality of each function:
countSetBits(‘mask’) :
This function takes an integer as an argument whose set bits are to be counted.
on(‘i’ , ‘mask’) :
This function takes two integers as arguments, ‘i’ and ‘mask’ where ‘mask’ is the integer whose ‘ith’ bit is to be checked if it is set or not.
isArrangementValid(‘row’, ‘currRow’, ‘prevRow’) :
This function takes character arguments: array/list ‘row’ which is the current row, Integer ‘currRow’ which is the arrangement of houses for current row and Integer ‘prevRow’ which is the arrangement of houses in the previous row.
This function checks if ‘currRow’ is valid with respect to ‘prevRow’ an array/list ‘row’:
getMaxHouses(‘Town’, ‘prevRow’, ‘i’):
This function takes arguments: array/list of array/list of characters ‘Town’ which is the original situation of town, Integer ‘prevRow’ which previous rows arrangement of houses, Integer ‘i’ which is index of current house, and returns the best answer for ‘ith’ row with respect to ‘prevRow’ and rows after ‘i’:
Call recursion on rows after ‘i’:
planTown(‘Town’):
This function takes grid ‘Town’ as argument and calls recursive function ‘getMaxHouses’ to get the best answer, and then returns it.
The approach is very similar to approach 1. What we will do here is that we will not make repetitive recursive calls to the recursive functions if we have already calculated an answer for a specific value.
But how do we know that there will be repeated recursive calls?
Let’s understand :
Suppose we are at the ‘ith’ row of ‘Town’ and we make the following 2 recursive calls:
Recursive call 1 from ‘ith’ row:
Recursive call 2 from ‘jth’ row:
From these 2 recursive calls from ‘ith’ row of ‘Town’ grid, we can see that both recursive calls were made from different arrangements (‘xth’ and ‘yth’ arrangement), but when we made recursive call from ‘i+1th’ row, arrangement ‘z’ is passed to ‘i+2th’ row. Hence, ‘zth’ arrangement from ‘i+1th’ row is passed 2 times this way but the same answer is returned from both calls. Hence, it is observed that repetitive recursive calls are made. So, to avoid these repetitive calls, we can store a previously calculated result in an array.
Below are the functionality of each function:
countSetBits(‘mask’) :
This function takes an integer as an argument whose set bits are to be counted.
on(‘i’ , ‘mask’) :
This function takes two integers as arguments, ‘i’ and ‘mask’ where ‘mask’ is the integer whose ‘ith’ bit is to be checked if it is set or not.
isArrangementValid(‘row’, ‘currRow’, ‘prevRow’) :
This function takes character arguments: array ‘row’ which is the current row, Integer ‘currRow’ which is the arrangement of houses for current row and Integer ‘prevRow’ which is the arrangement of houses in the previous row.
This function checks if ‘currRow’ is valid with respect to ‘prevRow’ and array ‘row’:
3. Run a for loop from 0 to ‘n’-1 (say iterator = ‘j’), to check for upper left and upper right houses:
4. Return true.
getMaxHouses(‘Town’, ‘prevRow’, ‘i’, ‘dp’):
This function takes arguments: array of array of characters ‘Town’ which is the original situation of town, Integer ‘prevRow’ which previous rows arrangement of houses, Integer ‘i’ which is index of current house, and ‘dp’ array which is used to store the calculated results to avoid repetitive recursive calls(memoization). This function returns the best answer for ‘ith’ row with respect to ‘prevRow’ and rows after ‘i’:
planTown(‘Town’):
This function takes grid ‘Town’ as argument and calls recursive function ‘getMaxHouses’ to get the best answer, and then returns it.
This approach uses the same idea as the top-down DP approach, but instead of making recursive calls to calculate for previous rows, we use iteration in a bottom-up manner.
Now, let’s discuss the approach: