How to find all sub rectangles using fastest algorithm? - 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.)

Related

Find the largest chessboard surface in 2D Matrix

I'm having a bit of difficulty by solving an exercise, hope I can get some help from you.
Given a 2D Array with N rows and M columns, and the array has only elements with the value 0 and 1.
Find the largest surface that is similar to a chessboard(where 0 are the white squares and 1 the black squares) and print the size of the surface(number of squares).
Constraints:
2<=N<=1000
2<=M<=1000
Example:
N=4, M=5
0 1 1 0 1
1 0 1 0 1
0 0 1 1 0
1 1 0 1 1
Output: Number of squares=5 (row 2-from column 1 to column 5)
Example:
N=3, M=4
0 0 1 0
1 1 0 0
1 0 1 0
Output: Number of squares=6 (from row 1 to row 3- from column 2 to column 3)
Flip every second cell in a checkerboard pattern
Find the largest rectangle containing only 0s or only 1s.
See Find largest rectangle containing only zeros in an N×N binary matrix for help on the 2nd part.
For your second example:
0 0 1 0
1 1 0 0
1 0 1 0
flipping every 2nd cell produces:
0 1 1 1
0 1 1 0
1 1 1 1
And you can see the rectangle of 1s that you're looking for.

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)?

Fill matrix randomly without row-repetitions

Please help. I'm new to matlab scripting and need a bit of help. I have a series of numbers:
A=[1 1 1 2 2 2 3 3 3 4 4 4 5]
which I want to fill randomly into an 8x12 matrix without having the same number in the same row. At the end I want all the "empty" cells of the 8x12 matrix being filled with 0's or nan.
an example could be:
result=
3 1 5 2 4 5 0 0 0 0 0 0
4 1 3 2 0 0 0 0 0 0 0 0
1 3 4 2 0 0 0 0 0 0 0 0
make sure A is sorted. A = sort(A)more info
make an empty matrix.
For each number in A: more info
find out how many repetitions of the number there are -> for loop in A, start is the first occurance of the number, end is the last, n = last-first+1
find all rows that have space for an extra number, just do a double for loop and keep track of elements that are zero
randomly pick n rows -> more info. To do this, make an array R of all available row indixes. Then take a random sample between 1..size(R,2) with the provided function and get all the values, you now have your row indixes.
randomly pick one of the empty spots in each of the selected rows and assign the number

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

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

permutation matrix

Is it possible to decompose a matrix A having n rows and n columns to sum of m [n x n] permutation matrices. where m is the number of 1's in each row and each column in matrix A?
UPDATE:
yes, this is possible. I came across such an exmaple which is shown below - but How can we generalize the answer?
What you want is called a 1-factorization. One algorithm is repeatedly to find a perfect matching and remove it; probably there are others.
For the first permutation matrix, take the first 1 in the first row. For the second row, take the first 1 that is in a column you don't already have. For the third row, take the first 1 that is in a column you don't already have. And so on. Do this for all rows.
You now have one permutation matrix.
Next subtract your first permutation matrix from the original. This new matrix now has m-1 ones in each row and column. So repeat the process m-1 more times, and you'll have your m permutation matrices.
You can skip the last step, because a matrix with one 1 in each row and column already is a permutation matrix. There's no need to do any calculations.
This is a greedy algorithm that doesn't always work. We can make it work by changing the selection rule slightly. See below:
For your example:
1 0 1 1
A = 1 1 0 1
1 1 1 0
0 1 1 1
In the first step, we pick (1,1) for the first row, (2,2) for the second row, (3,3) for the thrid row and (4,4) for the 4th row. We then have:
1 0 0 0 0 0 1 1
A = 0 1 0 0 + 1 0 0 1
0 0 1 0 1 1 0 0
0 0 0 1 0 1 1 0
The first matrix is a permutation matrix. The second matrix has exactly two 1's in each row and column. So we pick, in order: (1,3), (2,1), (3,2) and... we're in trouble: the rows that contain a 1 in column 4 have already been used.
So how do we fix this? Well, we can keep track of the number of 1's remaining in each column. Instead of picking the first column that is unused, we pick the column with the lowest number of 1's remaining. For the second matrix above:
0 0 1 1 0 0 X 0 0 0 X 0 0 0 X 0
B = 1 0 0 1 --> 1 0 0 1 --> 0 0 0 X --> 0 0 0 X
1 1 0 0 1 1 0 0 1 1 0 0 X 0 0 0
0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0
------- ------- ------- -------
2 2 2 2 2 2 X 1 1 2 X X X 1 X X
So we would pick column 4 in the second step, column 1 in the 3rd step, and column 2 in the 4th step.
There can always be only one column with one remaining 1. The other 1's must have been taken away in m-1 previous rows. If you had two such columns, one of them would have had to have been picked as the minimum column before.
This can be done easily using a recursive (backtracking OR depth-first traversal) algorithm. Here is the pseudo-code for its solution:
void printPermutationMatrices(const int OrigMat[][], int permutMat[], int curRow, const int n){
//curPermutMatrix is 1-D array where value of ith element contains the value of column where 1 is placed in ith row
if(curRow == n){//Base case
//do stuff with permutMat[]
printPermutMat(permutMat);
return;
}
for(int col=0; col<n; col++){//try to place 1 in cur_row in each col if possible and go further to next row in recursion
if(origM[cur_row][col] == 1){
permutMat[cur_row] = col;//choose this col for cur_row
if there is no conflict to place a 1 in [cur_row, col] in permutMat[]
perform(origM, curPermutMat, curRow+1, n);
}
}
}
Here is how to call from your main function:
int[] permutMat = new int[n];
printPermutationMatrices(originalMatrix, permutMat, 0, n);

Resources