I'd like to take a grid of 0's and 1's and arrive at all rectangles present in the grid, which share a common corner.
Similar to the Maximal Rectangle problem -
Link 1
Link 2
But instead of finding a single rectangle with the maximum area, I'd like to find all rectangles that share a common corner. IE if I specify coordinates (10,10) I'd like all possible rectangles that have a bottom left corner of 10,10.
Could someone help explain how I can adapt the implementation of the algorithm I linked to do what I described?
I am not sure about how to adapt the given algorithm for this problem, but I have a good way to solve this problem.
Say, we are given the bottom-left corner for the rectangles at (x1, y1). We keep a count of the number of rectangles(with value 1 and sharing the bottom-left corner) num and a horizontal value till which rectangles can be found at this value of y hval. Now, we traverse horizontally until hval or if we find a 0 in the way, since no rectangles can be made beyond this point. Now, we make this x the new hval. We move to the next row and do the same each time counting the number of rectangles we have passed.
The solution is O(n2). Since we used atmost 2*num steps the complexity of solution is also bounded by θ(num).
This python code sample can provide a better understanding:
num = 0
hval = len(board)
i = 1
x1=1
y1=1
x2 = x1
while (y1 < len(board) and i > 0):
i = 0
while (board[y1][x2] == 1 and x2 < hval):
num += 1
x2 += 1
i += 1
else:
hval = x2
y1 += 1
x2 = x1
print(num)
You don't want or need my linked answer for this. An easy way to do this is to first calculate the "integral image" I[][] of the input matrix M[][] -- that is, a matrix I[][] whose (x, y) entry is the sum of all entries below and to the left of (x, y) in the input matrix. This lets you easily compute the number of 1s in any given rectangle (x1, y1, x2, y2) in constant time using I[x2][y2] - I[x1-1][y2] - I[x2][y1-1] + I[x1-1][y1-1], if (x1, y1) is the bottom-left corner and (x2, y2) is the top-right corner. I[][] can be computed in a one-time O(n^2) preprocessing step.
For a given bottom-left corner (x1, y1), you can then simply loop through all widths w and heights h in increasing order using a pair of nested loops, testing whether the number of 1s in the rectangle (x1, y1, x1+w, y2+h) is the number of 1s that should be there in an all-1 rectangle -- i.e., (b+1)*(h+1). As soon as this fails to hold, exit that loop early (since clearly if some rectangle is not an all-1 rectangle, then no rectangle that contains it can be either).
This algorithm is of course O(n^2)-time for an n*n rectangle, but there is no avoiding this worst case (consider an input matrix in which every entry is 1).
Related
Given two line segments on a 2D grid (horizontal or vertical), how can I determine if they are adjacent?
Two line segments A, B are adjacent if there exists at least one pair of points (ax, ay) in A and (bx, by) in B that are adjacent.
Two points are adjacent if they are adjacent in the horizontal or vertical direction. Diagonals do not count.
It can be assumed that the line segments do not intersect and the length is >= 1.
Clearly a naive solution would be to loop through the points and check for adjacency but I'm looking for a closed form solution in constant time.
For example these line segments are adjacent:
B
AB
AB
AB
B
as are these
A
ABBB
A
but these are not (note the space)
BBB
A
A
A
A horizontal or vertical line segment on a 2d grid can be represented as a tuple (x, y, length, vertical) where vertical is a boolean indicating the length of the line. Alternatively, such a line segment could be represented as (x0, y0, x1, y1) where either x0 = x1 or y0 = y1.
We can reduce this problem to computing the Manhattan distance between two axis-aligned rectangles.
The key observation is that the dimensions are separable, specifically, the Manhattan distance is the Manhattan distance of the x intervals (in 1D) plus the Manhattan distance of the y intervals.
The Manhattan distance between 1D intervals [a, b] and [c, d] is max(max(a, c) − min(b, d), 0).
The overall test is max(max(x0, x0′) − min(x1, x1′), 0) + max(max(y0, y0′) − min(y1, y1′), 0) = 1.
For any line the line itself and its adjacent (including diagonally) points form a rectangle as e.g.:
++++++ +++
+----+ +|+
++++++ +|+
+++
For a line (x0, y0, x1, y1) this rectangle is defined by the coordinates (x0 - 1, y0 - 1, x1 + 1, y1 + 1), let's name them (X0, Y0, X1, Y1). You now just need to check if these rectangles intersect:
A:X0 <= B:X1 and B:X0 <= A:X1
and A:Y0 <= B:Y1 and B:Y0 <= A:Y1
This yet includes diagonal adjacency, though, so you need to check this case explicitly:
A:X0 == B:X1
A:X1 == B:X0
A:Y0 == B:Y1
A:Y1 == B:Y0
Just count how many of these equations apply, if exactly two of do so (more is not possible...), then the rectangles only intersect in a pair of corners, thus the lines are only diagonally adjacent.
I have an array of points, and my goal is to pick two so that I maximize the area of the rectangle formed by the two points (one representing the low left corner and the other one the right top corner).
I could do this in O(n^2) by just doing two for loops and calculating every single possible area, but I think there must be a more efficient solution:
max_area = 0
for p1 in points:
for p2 in points:
area = p2[0]p2[1] + p1[0]p1[1] - p2[1]p1[0] - p2[0]p1[1]
if area > max_area:
max_area = area
It's clear that I want to maximize the area of the second point with the origin (0,0) (so p2[0]p2[1]), but I'm not sure how to go forward with that.
Yes, there's an O(n log n)-time algorithm (that should be matched by an element distinctness lower bound).
It suffices to find, for each p1, the p2 with which it has the largest rectangular area, then return the overall largest. This can be expressed as a 3D extreme point problem: each p2 gives rise to a 3D point (p2[0], p2[1], p2[0] p2[1]), and each p1 gives rise to a 3D vector (-p1[0], -p1[1], 1), and we want to maximize the dot product (technically plus p1[0] p1[1], but this constant offset doesn't affect the answer). Then we "just" have to follow Kirkpatrick's 1983 construction.
Say you have a rectangle formed by four points: A (top left), B (top right), C (bottom right) and D (bottom left).
The idea is to find two points p1 and p2 that are the closest to B and D respectively. This means that p1 and p2 are the furthest possible from each other.
def nearest_point(origin, points):
nearest = None
mindist = dist(origin, points[0])
for p in points[1:]:
d = dist(origin, p)
if mindist > d:
mindist = d
nearest = p
return nearest
Call it for B and D as origins:
points = [...]
p1 = nearest_point(B, points) # one for loop
p2 = nearest_point(D, points) # one for loop
Note that there can be multiples closest points which are equally distant from the origin (B or D). In this case, nearest_point() should return an array of points. You have to do two nested for loops to find the furthest two points.
Divide and conquer.
Note: This algorithm presumes that the rectangle is axis-aligned.
Step 1: Bucket the points into a grid of 4x4 buckets. Some buckets
may get empty.
Step 2: Using the corners of the buckets, calculate
maximum areas by opposite corners between not empty buckets. This may result in
several pairs of buckets, because your work with corners, not points. Notice also that you use left corners for left buckets, and so for bottom, right, top corners for those b,r,t buckets. That's why an even number is used for the size of the grid.
Step 3: Re-bucket each bucket selected in step 2 as a new, smaller, 4x4 grid.
Repeat steps 2 & 3 until you get only a pair of buckets that contain only a point in each bucket.
I have not calculated the complexity of this algorithm. Seems O(n log(n)).
Given a rectangular grid of size N × M, namely, there are cells (x, y) for 1 ≤ x ≤ N, 1 ≤ y ≤ M.
Two cells are adjacent if they share a side. More formally, two cells (x1, y1), (x2, y2) are adjacent if |x1 − x2| + |y1 − y2| = 1. Between two adjacent cells there can be a wall. Two cells a and b are connected if there is a way between them (in other words there is a sequence of cells c[1], c[2], ..., c[k] such that c[1] = a, c[k] = b, and for each 1 ≤ i < k, c[i] and c[i+1] are adjacent cells without wall between them).
Now we are given Q queries, each of them is of following four types.
1 x y - Build the wall between cells (x, y) and (x, y+1). If there is already exist a wall between them, this query is ignored.
2 x y - Build the wall between cells (x, y) and (x+1, y). If there is already exist a wall between them, this query is ignored.
3 x1 y1 x2 y2 - Check if cells (x1, y1) and (x2, y2) are connected. Answer to this query is a YES or NO
4 - We need to tell the size of the largest connected component. A connected component is a set of sells wherein each two cells are connected. The size of a connected component is a number of the cells in it.
Note : We can assume that there are no walls on the grid before the queries.
Now given N , M and Q queries we need to tell answer for query of type 3 and 4.
My Approach : I am currently thinking to do it by making a graph and then doing dfs sort of thing for each query. Can this approach be made efficient or is there some other better approach to solve this problem ?
The size of grid is 1000 X 1000 at max. And queries can be up to 10^6
Example : Let N=3 and M=4 and at start we are asked query of type 3 that is (1,1) connected to (3,4) then answer is YES as earlier grid is like this :
http://postimg.org/image/5qoug2dov/
Now suppose we have queries of type 1 and 2 and grid become something like this :
http://postimg.org/image/tm14jtg9h/
Now the answer for same query 3 is NO
Assuming that you can answer queries offline, then working on them in reverse order turns this into an incremental connectivity problem that is perfect for a disjoint-set data structure whose root nodes are augmented with the total number of nodes in the set.
Recently I have started doing some research on the SAT (Separating Axis Theorem) for collision detection in a game I am making. I understand how the algorithm works and why it works, what I'm puzzled about is how it expects one to be able to so easily calculate the projection of the shape onto different axes.
I assume the projection of a polygon onto a vector is represented by line segment from point A to point B, so my best guess to find points A and B would be to find the angle of the line being projected onto and calculate the min and max x-values of the coordinates when the shape is rotated to the angle of the projection (i.e. such that it is parallel to the x-axis and the min and max values are simply the min and max values along the x-axis). But to do this for every projection would be a costly operation. Do any of you guys know a better solution, or could at least point me to a paper or document where a better solution is described?
Simple way to calculate the projection of the polygon on line is to calculate projection of all vertex onto the line and get the coordinates with min-max values like you suggested but you dont need to rotate the polygon to do so.
Here is algorithm to find projection of point on line :-
line : y = mx + c
point : (x1,y1)
projection is intersection of line perpendicular to given line and passing through (x1,y1)
perdenicular line :- y-y1 = -1/m(x-x1) slope of perpendicular line is -1/m
y = -1/m(x-x1) + y1
To find point of intersection solve the equation simultaneously :-
y = mx + c , y = -1/m(x-x1) + y1
mx + c = -1/m(x-x1) + y1
m^2*x + mc = x1-x + my1
(m^2+1)x = x1 + my1 - mc
x = (x1-my1 - mc)/(m^2+1)
y = mx + c = m(x1-my1-mc)/(m^2+1) + c
Time complexity : For each vertex it takes O(1) time so it is O(V) where V is no of vertex in the polygon
If your polygon is not convex, compute its convex hull first.
Given a convex polygon with n vertices, you can find its rotated minimum and maximum x-coordinate in n log n by binary search. You can always test whether a vertex is a minimum or a maximum by rotating an comparing it and the two adjacent vertices. Depending on the results of the comparison, you know whether to jump clockwise or counterclockwise. Jump by k vertices, each time decreasing k by half (at the start k=n/2).
This may or may not bring real speed improvement. If your typical polygon has a dozen or so vertices, it may make little sense to use binary search.
I have encountered the following interesting problem while preparing for a
contest.
You have a triangle with sides of length a, b, c and a rope of length L. You need to find
the surfaced enclosed by the rope that has the maximum surface area and it has to be entirely inside the triangle.
So, if L = a + b + c, then it's the area of the triangle.
Else, we know that the circle has the biggest surface to perimeter area, so if L is smaller or equal to the perimeter of the inscribed circle of the triangle, then the area will be the area of the circle of perimeter L.
So, the remaining case is alfa < L < a + b + c, where alfa is the perimeter of the inscribed circle .
Any ideas would be great!
EDIT: I would like to know if I should focus on some kind of algorithm for solving this
or trying to figure it out a mathematical formula. The contest contains somehow a combination of both. The edges can be as long as 100 and the precision of a,b,c,L is of 4 digits after the decimal point .
After reading the answers to this question: https://math.stackexchange.com/questions/4808/why-circle-encloses-largest-area, I agree with n.m., and think the optimal curve verifies:
Curvature is either constant, or flat when it touches the triangle, meaning it is composed of segments lying on the triangle sides, and circle arcs, all sharing the same radius.
There are no angles, meaning the arcs are tangent to the triangle sides.
With these conditions, the solution is obtained by three circles of same radius R, each tangent to two sides of the triangle (see below). When R varies between 0 and the radius of the inscribed circle, we start from the triangle itself, and end to the inscribed circle, where all three circles coincide. The length of the curve is the perimeter of the circle of radius R + the perimeter (p) of the smaller triangle: L = 2*PiR + p. The area is the area (a) of the smaller triangle + one disc of radius R + the remaining rectangles: A = PiR^2 + p*R + a.
Since a circle has the largest Area/Perimeter, start with the inscribed circle. If L is less than that circumference, then shrink appropriately. If L is longer, grow whichever of the 3 arcs maximizes dA/dL. I don't know if there's a closed form, but the largest arc will be in the 3rd of the triangle with the sides most approaching parallel.
It should be trivial to solve this algorithmically. With 4 decimals of precision, increment by 0.0001 checking each arc to see which has the greatest dA/dL for that single increment.
I worked up a drawing of the geometry overnight:
The inscribed circle is constructed by bisecting each of the angles and finding the intersections of the bisectors. I've labeled the half-angle "a1" (and all related variables have '1'). The area of the non-circular portion is two trapezoids (one denoted with the red outline). We can calculate the area for a single trapezoid as L1 * (m1 + R)/2 (note that when L1, L2, L3 are all zero, these trapezoids are all zero, and we just get the inscribed circle area). The circular cap has a radius of m1 to remain tangent with the side of the triangle. For a given choice of L1, m1 = R(x1-L1)/x1.
From here you can easily calculate the perimeter and area of each of the three sectors and solve numerically.
I cannot prove that this is the largest area, just that this is how to calculate the area and perimeter of this construction.
..answering my own comment/question, it can be proved that the radii must be equal,
Here is a useful formula:
the gray area A is
A = r^2 ( alpha - Pi + 2/tan(alpha/2) ) /2
but even more useful..the arc length is simply:
s = 2 ( b - A/r )
from here it is straightforward to show the three radii must be equal to each other:
writing the rope length and enclosed area:
ropelength = trianglelength - 2 Sum[r[i] a[i] ]
ropearea = trianglearea - Sum[r[i]^2 a[i] /2 ]
where
a[i]=( alpha[i] - Pi + 2/tan(alpha[i]/2) )
after a bit of manipulation maximizing the area leads to all r[i] equal. Note the three a[i], ropelength,trainglearea,trianglelength are all constants that you do not need to work out. Pedantically solve for r[l] = f( constants, r[2],r[3] ) sub into the second expression and solve for d ropearea /d r[2] = 0 and d /d r[3] = 0 with the result:
r =(1/2) (triangle_length - rope_length) /(Sum(1/tan(alpha[i]/2)) - Pi)
(the messy expression for a[i] is substituted only at the last step ) finally..
ropearea = trianglearea - (trianglelength-ropelength)^2/(8 Sum[a[i])
= trianglearea - (1/2)(trianglelength-ropelength) r
edit -- a useful identity ..with a,b,c, the lengths of the sides.
Sum(1/tan(alpha[i]/2)) = Sqrt( S^3 / ((S-a)(S-b)(S-c)) )
S = 1/2 (a+b+c) ! S is semiperimeter not to be confused with arc length s
the above expressions then can be used to reproduce the formula for an inscribed circle,
rinscribed = Sqrt( ((S-a)(S-b)(S-c)) / S )
If the perimeter of the rope is too small or too large, the answers are trivial. The interesting case is a shape with 6 vertices that goes line-arc-line-arc-line-arc. The arc are all tangent to their neighbouring lines and their radii are equal. I don't have a rigorous proof, but imagine a 2D balloon filled with air and squeezed between the sides of the triangle.
It is easy to express the overall shape and thus the perimeter given the radius; the opposite direction (perimeter to radius) is then easily found numerically.