Choose max number of non-overlapping 2x2 squares in binary bitmap - algorithm

Given a rectangle consisting of 1's and 0's, how can I find the maximum number of non-overlapping 2x2 squares of 1's?
Example:
0110
1111
1111
The solution would be 2.
I know it can be solved with Bitmask DP; but I can't really grasp it - after playing with it for hours. How does it work and how can it be formalised?

I wanted to point out that the graph we get by putting vertices at the centers of squares and joining them when they overlap is not claw-free:
If we take (in the full plane) a 2x2 square and three of the four diagonally overlapping 2x2 squares, they form the induced subgraph
• •
\ /
•
/
•
This is a claw, meaning that any region containing those squares corresponds to a non-claw-free graph.

If you build a graph where every node represents a 2x2 square of 1's and there is an edge between two nodes if they overlap, then the problem is now: find the maximum independent set in this graph.

Here is a dynamic programming solution.
The state is (row number, mask of occupied cells, shift position). It looks like this:
..#..
.##..
.#...
.#...
In this case, the row number is 2(I use zero-bases indices), the mask depends on whether we take a cell with # or not, the shift position is 1. The number of states is O(n * m * 2 ^ n). The value of a state is the maximum number of picked 2x2 squares. The base case is f(1, 0, 0) = 0(it corresponds to the first row and no 2x2 squares picked so far).
The transitions are as follows:
..#.. ..#..
.00.. -> ..1..
.0... .11..
.#... .#...
This one can be used if and only if the square consists of ones in the original matrix and there were zeros in the mask(it means that we pick this square).
The other one is:
..#.. ..#..
.##.. -> ..#..
.#... .#0..
.#... .#...
This one is always applicable. It means that we do pick this 2x2 square.
When we are done with one row, we can proceed to the next one:
..#.. ..#0.
..#.. -> ..#..
..#.. ..#..
.##.. ..#..
There are at most two transitions from each state, so the total time complexity is O(n * m * 2 ^ n). The answer the maximum among all masks and shifts for the last row.

edit 20:18, there is a counterexample posted by #ILoveCoding
My intuition says, that this will work. I am unable to prove it since I'm not advanced enough. I can't think of any counterexample though.
I will try describe the solution and post the code, please correct me if my solution is wrong.
First we load input to an array.
Then we create second array of the same size and for every possible placing of 2x2 square we mark 1 in the second array. For the example posted by OP this would look like below.
0 1 0 0
1 1 1 0
0 0 0 0
Then for every 1 in second array we calculate the number of neighbours (including diagonals) + 1 (because if it doesn't have any neighbours we have to still see it as 1). We set those new numbers to the array. Now it should look like this.
0 4 0 0
3 4 3 0
0 0 0 0
Then for every non-zero value in the array we check whether it has any neighbour with bigger or equal value. If it has then move on since it can't be in the solution.
If we don't find any such value then it will be in the solution. We have to reset to zero every neighbour of the original value (because it can't be in the solution, it would overlap the solution.
So the first such number found should be 2 on the left. After processing it the array should look like following.
0 0 0 0
3 0 3 0
0 0 0 0
When we check the other 3 situation is the same.
We end up with non-zero values in the array indicating where top left corners of 2x2 squares are.
If you need the numer of them just traverse the array and count non-zero elements.
Another example
1111 -> 1 1 1 0 -> 4 6 4 0 -> 4 0 4 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 0 0 0 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 6 0 6 0
1111 -> 1 1 1 0 -> 6 9 6 0 -> 0 0 0 0
1111 -> 1 1 1 0 -> 4 6 4 0 -> 4 0 4 0
1111 -> 0 0 0 0 -> 0 0 0 0 -> 0 0 0 0
The code I write can be found here
http://ideone.com/Wq1xRo

Related

Segment tree built on "light bulbs"

I have encountered following problem:
There are n numbers (0 or 1) and there are 2 operations. You can swich all numbers to 0 or 1 on a specific range(note that switching 001 to 0 is 000, not 110) and you can also ask about how many elements are turned on on a specific range.
Example:
->Our array is 0100101
We set elements from 1 to 3 to 1:
->Our array is 1110101 now
We set elements from 2 to 5 to 0:
->Our array is 1000001 now
We are asking about sum from 2nd to 7th element
-> The answer is 1
Brute force soltion is too slow(O(n*q), where q is number of quetions), so I assume that there has to be a faster one. Probably using segment tree, but I can not find it...
You could build subsampling binary tree in the fashion of mipmaps used in computer graphics.
Each node of the tree contains the sum of its children's values.
E.g.:
0100010011110100
1 0 1 0 2 2 1 0
1 1 4 1
2 5
7
This will bring down complexity for a single query to O(log₂n).
For an editing operation, you also get O(log₂n) by implementing a shortcut: Instead of applying changes recursively, you stop at a node that is fully covered by the input range; thus creating a sparse representation of the sequence. Each node representing M light bulbs either
has value 0 and no children, or
has value M and no children, or
has a value in the range 1..M-1 and 2 children.
The tree above would actually be stored like this:
7
2 5
1 1 4 1
1 0 1 0 1 0
01 01 01
You end up with O(q*log₂n).

Finding probability that chess Knight will stay on chessboard after k moves with dynamic prgramming

I was trying out "Knight Probability in Chessboard" problem from leetcode:
Given n, k, row and column, we have to find the probability that knight initially kept at cell indexed by [row,column] will stay on n x n chessboard after k moves.
I wanted to do it by addition, that is, maintain number of ways we can get to cell at index [x,y] in kth step at dynamic programming memory location indexed [x,y,k]. Then sum counts in all cells at kth index and then divide it by 8^k. That is, if I start at index [0,0], with n=4, the values at successive k-th index will be:
After step 1:
0 0 0 0
0 0 1 0
0 1 0 0
0 0 0 0
After step 2:
4 0 2 0
0 0 0 2
2 0 0 0
0 2 0 4
After step 3:
0 6 0 0
6 0 11 0
0 11 0 6
0 0 6 0
Only first step output seems to be correct. After second step, the sum is 2+2+2+2+4+4=16 and the probability is 16/8^2 = 0.25. However, the actual answer is 0.125. After third step, the sum becomes 6+6+6+6+11+11=46 and the probability is 46/8^3 = 0.0898. But, the actual answer is 0.039. Where does this dynamic programming approach make mistake?
Sample calculation for step 2
Bottom up approach:
Start by filling P(x_start, y_start, 0) = 1 and setting (x_start, y_start) in a map (from positions to booleans) previous_layer_map. Also, set the counter current_layer to 1.
Iterate though each of the n^2 positions of the board. For each of them, check in O(1) if it reaches a square in previous_layer_map. If so:
If (x, y) was never saw before in the current layer (current_layer_map[x][y] == false), fill
P(x, y, current_layer) = P(x_reached, y_reached, current_layer-1)/8
and set (x, y) in current_layer_map.
Else, set
P(x, y, current_layer) += P(x_reached, y_reached, current_layer-1)/8
After you finish iterating though each of the n^2 positions of the board, empty previous_layer_map, fill it with the elements of current_layer_map and empty current_layer_map. Also, increase the counter current_layer. Then, start a new iteration. Go like this until you reach the k-th layer.
Total time complexity: O(k * n^2).
Top down approach:
Let P(x, y, k) be the probability that the knight is at the square (x, y) at the k-th step. Look at all squares that the knight could have come from (you can get them in O(1), just look at the board with a pen and paper and get the formulas from the different cases, like knight in the corner, knight in the border, knight in a central region etc). Let them be (x1, y1), ... (xj, yj). For each of these squares, what is the probability that the knight jumps to (x, y) ? Considering that it can go out of the border, it's always 1/8. So:
P(x, y, k) = (P(x1, y1, k-1) + ... + P(xj, yj, k-1))/8
The base case is k = 0.
P(x, y ,0) = 1 if (x, y) = (x_start, y_start) and P(x, y, 0) = 0 otherwise.
That is your recurrence formula. You can use dynamic programming to calculate it.
Open question: how to analyze the time complexity of this solution ? Is it equivalent to the bottom-up approach described in my other answer ?
I was incorrecty incrementing the numbers. For example in the diagram shown at the end of original question, red arrows increments from 1 to 2. It shouldnt be the case as going from one cell to next represents the same single path to next cell. It does not create two different paths to next cell. Same is the case with blue arrow. So, corrected steps are:
After step 1
0 0 0 0
0 0 1 0
0 1 0 0
0 0 0 0
After step 2
2 0 1 0
0 0 0 1
1 0 0 0
0 1 0 2
After step 3
0 2 0 0
2 0 6 0
0 6 0 2
0 0 2 0
and (2+2+2+2+6+6)/8^3 = 20/8^3 = 0.039
which is the correct answer!

How to find all sub rectangles using fastest algorithm?

An example , suppose we have a 2D array such as:
A= [
[1,0,0],
[1,0,0],
[0,1,1]
]
The task is to find all sub rectangles concluding only zeros. So the output of this algorithm should be:
[[0,1,0,2] , [0,1,1,1] , [0,2,1,2] , [0,1,1,2] ,[1,1,1,2], [2,0,2,0] ,
[0,1,0,1] , [0,2,0,2] , [1,1,1,1] , [1,2,1,2]]
Where i,j in [ i , j , a , b ] are coordinates of rectangle's starting point and a,b are coordinates of rectangle's ending point.
I found some algorithms for example Link1 and Link2 but I think first one is simplest algorithm and we want fastest.For the second one we see that the algorithm only calculates rectangles and not all sub rectangles.
Question:
Does anyone know better or fastest algorithm for this problem? My idea is to use dynamic programming but how to use isn't easy for me.
Assume an initial array of size c columns x r rows.
Every 0 is a rectangle of size 1x1.
Now perform an "horizontal dilation", i.e. replace every element by the maximum of itself and the one to its right, and drop the last element in the row. E.g.
1 0 0 1 0
1 0 0 -> 1 0
0 1 1 1 1
Every zero now corresponds to a 1x2 rectangle in the original array. You can repeat this c-1 times, until there is a single column left.
1 0 0 1 0 1
1 0 0 -> 1 0 -> 1
0 1 1 1 1 1
The zeroes correspond to a 1xc rectangles in the original array (initially c columns).
For every dilated array, perform a similar "vertical dilation".
1 0 0 1 0 1
1 0 0 -> 1 0 -> 1
0 1 1 1 1 1
| | |
V V V
1 0 0 1 0 1
1 1 1 -> 1 1 -> 1
| | |
V V V
1 1 1 -> 1 1 -> 1
In these rxc arrays, the zeroes correspond to the subrectangles of all possible sizes. (Here, 5 of size 1x1, 2 of size 2x1, 2 of size 1x2 and one of size 2x2.)
The total workload to detect the zeroes and compute the dilations is of order O(c²r²). I guess that this is worst-case optimal. (In case an array contains no zeroes, there is no need to continue any dilation.)

Is there an algorithm that divide a square cell grid map into 3 or 4 equal spaces?

So for example I have divide my map into something like this:
click on link
the matrix representative would be
0 1 0 1 0
1 1 1 1 0
0 1 1 1 1
0 1 0 0 0
one of the way I could divide it into even-ish would be:
click to see
where total square is 11 and since 11/3 gives us a decimal, I need to have 2 space with 4 square and one space with 3 squares.
but I don't know an algorithm that will be able to divide a small map like that.
there is probably a code that will be able to solve that particular map, but what if it is like :
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 0
0 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1
Each value is a square in the map and 1 is the square that should be considered. 0 is an empty/null space that is not part of the map and should not be taken into consideration when dividing the map.
So far I try a for loop adding all value and divide by 3 to determine how many squares is needed for each space. Also, if I get a decimal, then one space can have one more square than the other. So in this problem there is 36 squares so if I try to divide it into 3 space, then each space would have 12 squares.
So I am looking to see if there is an algorithm that will be able to solve all types of map.
This is actually NP-hard for k>=2, where you want k=3 or k=4:
theorem 2.2 in On the complexity of partitioning graphs into connected subgraphs - M.E. DYER, A.M. FRIEZE
You can get a decent answer by greedily removing nodes from your graph, and backtracking if you can't merge the remaining nodes.
It would help if you gave a more rigorous definition of 'even-ish' - for example, consider a map with 13 nodes - Would you rather have divisions of size (4,4,5), (3,3,3,4), (4,4,4,1), (5,5,3), or (4,4,3,2)?

Find minimum number of rectangles of length 2 in a grid of binary values

Given a grid, I need to "cover" the true values with rectangles. The rectangles can only be horizontal or vertical and they can cover two cells at max.
For example, in this case:
1 1 1 0 0
1 0 0 0 1
0 0 0 1 0
the minimum number of ractangles is 4: 1 from [0][0] to [1][0], 2 from [0][1] to [0][2], 3 with only [1][4] (since there aren't any adjacent 1s in the up, down, left and right directions) and the last one with only [2][3] in it.
I suppose, the problem comes when the grid has many consecutive 1s that split in many directions. For example
1 1 1 1 1
1 0 0 0 0
1 0 0 1 0
1 1 1 1 0
or
1 1 1
1 0 1
1 1 1
I cannot think of a pretty efficient algorithm to solve this problem, a greedy approach seems to be ineffective.
Any help would be really much appreciated, thanks.
EDIT:
The greedy algorithm I've tried: scan the matrix 1 row at a time, if there's a 1 in the current position, then check if there's another 1 in the next row position [rowIndex][columnIndex + 1] and "cover" both with one rectangle. If not, check the cell below the current position [rowIndex + 1][columnIndex] and do as before. If there aren't any 1s in these positions, cover only the current cell. As you can see, this algorithm doesn't work in the first case. Perhaps the algorithm must know all the consecutive 1s to compute the minimum number of rectangles. Because of this, I'm wondering if some graph stuff comes in, but I can't still think of an optimal solution.
I would simply go through the matrix and as soon I see a 1 I try to create a new rectangle with an adjacent 1 which can be on the same line or row and has no other adjacent 1 otherwise the rectangle will cover only the current cell and then you scan the matrix until you find a new uncovered 1 or you have scanned the enteir matrix, in this way you can cover all the 1 with the minumum number of rectangle (if I'm not wrong).
for i=0 to N
for j=0 to M
if (1==matrix[i][j] AND notCovered(i,j)){
k,l=adjacent(i,j)//return an adjacent 1 that cannot be covered, if all the adjacent 1 can be covered return the one on the same row
if (k AND l == VOID )
cover (i,j)
else
cover (i,j)(k,l)
}
Of course you can do some improvement on this algorithm, I hope this will help you

Categories

Resources