Given n points on the plane. No 3 are collinear.
Given the number k.
Find the subset of k points, such that the convex hull of the k points has minimum perimeter out开发者_开发技巧 of any convex hull of a subset of k points.
I can think of a naive method runs in O(n^k k log k). (Find the convex hull of every subset of size k and output the minimum).
I think this is a NP problem, but I can't find anything suitable for reduction to.
Anyone have ideas on this problem?
An example,
the set of n=4 points {(0,0), (0,1), (1,0), (2,2)} and k=3
Result:
{(0,0),(0,1),(1,0)}
Since this set contains 3 points the convex hull of and the perimeter of the result is smaller than that of any other sets of 3 points.
This can be done in O(kn^3) time and O(kn^2) space (or maybe O(kn^3) if you want the actual points).
This paper: http://www.win.tue.nl/~gwoegi/papers/area-k-gons.pdf
by Eppstein et al, has algorithms to solve this problem for minimum perimeter and other weight functions like area, sum of internal angles etc which follow certain constraints, even though the title says minimum area (See Corollary 5.3 for perimeter).
The basic idea is a dynamic programming approach as follows (read the first few paragraphs of Section 4):
Suppose S is the given set of points and Q is the convex hull of k points with minimum perimeter.
Let p1 be the bottom-most point of Q, p2 and p3 are the next points on the hull in counter-clockwise order.
We can decompose Q into a triangle p1p2p3 and a convex hull of k-1 points Q' (which shares the side p1p3 with triangle p1p2p3).
The main observation is that Q' is the optimal for k-1, in which the bottommost point is p1 and the next point is p3 and all the points of Q' lie on the same side of the line p2->p3.
Thus maintaining a 4d array of optimum polygons for the each quadruple (pi, pj, pk, m) such that
- the polygon is a convex hull of exactly m points of S.
- pi is the bottom most point of the polygon.
- pj is the next vertex in counter-clockwise order,
- all points of the polygon lie to the left of the line pi -> pj.
- all points lie on the same side of pj->pk as pi does.
can help us find the optimum polygons for m=k, given the optimum polygons for m <= k-1.
The paper describes exactly how to go about doing that in order to achieve the stated space and time bounds.
Hope that helps.
It's not exactly pretty solution. In fact, it's quite a pain to implement, but it surely gives polynomial complexity. Although complexity is also big (n^5*k is my rough estimate), someone may find a way to improve it or find here an idea for better solution. Or it may be enough for you: even this complexity is much better than bruteforce.
Note: optimal solution (set S
) with hull H
includes all points from orignal set inside H
. Otherwise, we could throw away one of the border points of H
and include that missed point, reducing perimeter.
(update just like 'optimization' mbeckish posted)
Assumption: no two points from the set form a vertical line. It can be achieved easily by rotating whole set of points by some irrational angle around origin of coordinates.
Due to assumption above, any complex hull has one leftmost and one rightmost point. Also, these two points divide the hull into top
and bottom
parts.
Now, let's take one segment from the top
part of this hull and one from the bottom
part. Let's call those two segments middle segments
and perimeter of the right part of this hull - right
perimeter.
Note: those two segments is all we need to know about right part of our convex hull to continue building it to the left. But having just two points instead of 4 is not enough: we could not uphold condition of 'convexness' this way.
It leads to a solution. For each set of points {p0, p1, p2, p3} and number i
(i <= k) we store minimal right
perimeter that can be achieved if [p0, p1], [p2, p3] are two middle
segments and i
is the number of points in the right
part of this solution (including the ones inside of it, not only on the border).
We go through all points from right to left. For each new point p
we check all combinations of points {p0, p1, p2, p3} such that point p can continue this hull to the left (either on the top
or on the bottom
part). For each such set and size i
, we already store optimal perimeter size (see paragraph above).
Note: if you add point p
to a right-hull
formed by points {p0, p1, p2, p3}, you'll increment set size i
at least by 1. But sometimes this number will be > 1: you'll have to include all points in the triangle {p, p0, p2}. They aren't on the hull, but inside it.
Algorithm is over :) In addition, despite scary complexity, you may note that not all segments [p0, p1], [p2, p3] can be middle
segments: it should reduce actual computation time substantially.
update This provides only optimal perimeter size, not the set itself. But finding the set is simple: for each 'state' above you store not only perimeter size, but also last point added. Then, you can 'trace' your solution back. It's quite standard trick, I suppose it's not a problem for you, you seem to be good at algorithms :)
update2 This is essentially DP (dynamic programming), only a bit bloated
One possible optimization: You can ignore any subsets whose convex hull contains points that are not in the subset.
Proof:
If your convex hull contains points that are not in your subset, then remove a point from your subset that is on the hull, and replace it with a point in the interior of the hull. This will yield a hull of equal or smaller perimeter.
In the planar case, you can use an algorithm known as the Jarvis march, which has worst case complexity O(n^2). In this algorithm, you start building a hull at an arbitrary point and then check which point needs to be added next. Pseudocode taken from wikipedia:
jarvis(S)
pointOnHull = leftmost point in S
i = 0
repeat
P[i] = pointOnHull
endpoint = S[0] // initial endpoint for a candidate edge on the hull
for j from 1 to |S|-1
if (S[j] is on left of line from P[i] to endpoint)
endpoint = S[j] // found greater left turn, update endpoint
i = i+1
pointOnHull = endpoint
until endpoint == P[0] // wrapped around to first hull point
As far as I understand it, convex hulls are unique to each set of points, so there is no need to find a minimum. You just find one, and it will be the smallest one by definition.
Edit
The posted solution solves for the convex hull with the fewest number of points. Any hull with more points will have a longer perimeter, and I misunderstood the question to seeking a minimum perimeter, instead of a minimum perimeter for a set with K points.
This new problem is probably NP as suspected, and most similar to the longest path problem. Unfortunately, I lack the ingenuity to provide a worthwhile reduction.
精彩评论