The Ultimate Ninja Ankush, has prepared a test for all of his fellow Ninja students, but since he is the Ultimate Ninja, he does not like cheating, and since his students are also ninjas, they broke some chairs in the dojo while practicing their moves.
The class consists of ‘M’ * ‘N’ seats, represented in a matrix ‘SEATS’. Among the seats, some of the seats are broken. If a seat is broken, it is denoted by '#' character otherwise it is denoted by a '.' character, denoting that the seat can be occupied. A Ninja can’t sit in a broken seat.
Ankush wants to avoid cheating at any cost. According to his observations, a student can see the answers of four neighboring students sitting next to the left, right, upper left, and upper right, but they cannot see the answers of the student sitting directly in front or behind him. Ankush is very busy so he wants to use the dojo to the fullest. More formally he wants to know the maximum number of ninja students that can be placed in the dojo.
For example
Given:
‘M’ = 3, ‘N’ = 3.
‘SEATS’ = {
{‘.’, ‘.’, ‘.’},
{‘#’,’#’, ‘#’},
{‘.’,’.’,’.’}
}
The answer will be 4, since 4 students can be placed at the four corners, i.e. (0,0), (2,2), (2,0), and (0,2) such that no cheating is possible.
The first line of input contains an integer ‘T’ denoting the number of test cases.
The first line of each test case contains two space-separated integers, ‘M,’ where ‘M’ is the number of rows in ‘SEATS’ and ‘N’ where ‘N’ is the number of columns in ‘SEATS’.
The next ‘M’ line contains ‘N’ space-separated integers which tell if the seat is broken or in good condition.
Output Format :
For each test case, You are supposed to return an integer that denotes the maximum number of students that can be placed such that no cheating is possible.
Note:
You are not required to print the expected output; it has already been taken care of. Just implement the function.
1 <= ‘T’ <= 10
1 <= ‘N’ <= 10
1 <= ‘M’ <= 10
Time Limit: 1sec.
2
3 3
. . .
# # #
. . .
2 4
# . # .
# # . .
4
3
In the first test case, The answer will be 4, since 4 students can be placed at the four corners, i.e. (0,0), (2,2), (2,0), and (0,2) such that no cheating is possible.
In the second test case, The answer will be 3, since we can place 3 students at 3 different places, i.e. (0,1), (0,3), (1,3), such that no cheating is possible.
2
3 3
. . .
# . #
# . .
2 4
. # # #
# . . .
3
2
Can we use bitmasks to denote the state of each row?
In computing, numbers are internally represented in binary. This means, where you use an integer type for a variable, this will actually be represented internally as a summation of zeros and ones.
Bit masking allows you to use operations that work on bit-level.
You apply a mask to a value, wherein in our case the value is our state 00000101 and a mask is again a binary number, which indicates the bits of interest.
The idea is to use a bitmask to denote the state of each row, where 1 denotes that the seat is good and students can be placed there and 0 denotes that the seat is broken.
When we arrange for the students to sit in this row, we can also use ‘N’ bits to represent the students. The i-th bit is 1 if and only if the i-th seat is occupied by a student. We should notice that n bits representing students must be a subset of ‘N’ bits representing seats.
Since there will be recurring problems, we use a ‘dp[i][j]’ table to store and cache the states, where ‘i’ denotes the row and ‘j’ is the ‘mask’ of seated students.
We denote ‘dp[i][mask]’ as the maximum number of students for the first ‘i’ rows while the students in the i-th row follow the masking mask. There should be no adjacent valid states in the mask. The transition function is:
‘dp[i][mask]’ = max(‘dp[i - 1][mask']’) + number of valid bits(mask)
where mask' is the configuration of students for the (i-1)-th row. To prevent students from cheating, the following equation must hold:
If these two equations hold and ‘dp[i - 1][mask']’ itself is valid, we could then transition from ‘dp[i - 1][mask']’ to ‘dp[i][mask]’ according to the transition function.
The steps are as follows:
O(M * (4 ^ N)), Where ‘M’ is the number of rows, and ‘N’ is the number of columns.
Since we are trying all possible configurations of columns, twice for every row, the overall time complexity will be O(M * (2 ^ N) * (2 ^ N)) = O(M * (4 ^ N).
O(M * (2 ^ N)), Where ‘M’ is the number of rows, and ‘N’ is the number of columns.
Since we are using a 2-D array to store the answers of each configuration corresponding to every row. So, the number of rows are M and the total number of configurations are 2^N. Hence, the overall space complexity will be O(M * (2 ^ N)).