问题描述:在一个点的集合中,选择最少的点,使得这些点组成的多变形可以围住其他所有的点,如下图所示:
解决方法:本文介绍的是Gift−Wrapping算法,主要步骤如下:
1.找到一个最边缘点(如最左下角点)
2.从这个点出发,逆时针寻找下一个点,使得这两个点的连线可以把其他所有点分割到一边:
3.以找到的点为出发点,寻找下一个符合条件的点
4.单找到的点为最开始的出发点时停止,此时所有找到的点加上出发点即为所需要求得的点:
代码示例:
import java.util.HashSet;
import java.util.Set;
public class convexHull {
public static void main(String[] args){
Set<Point> points = new HashSet<Point>();
Set<Point> convexHull = new HashSet<Point>();
Point p11 = new Point(1, 1);
Point p1010 = new Point(10, 10);
Point p110 = new Point(1, 10);
Point p23 = new Point(2, 3);
points.add(p11);
points.add(p1010);
points.add(p110);
points.add(p23);
convexHull = getconvexHull(points);
for(Point i:convexHull){
System.out.println(i.x()+","+i.y());
}
}
public static Set<Point> getconvexHull(Set<Point> points){
Set<Point> p = new HashSet<>();
if(points.isEmpty()){
return points;
}
Point a = new Point(Integer.MAX_VALUE,Integer.MAX_VALUE);
for (Point i : points) {
if (i.x() < a.x() || i.x() == a.x() && i.y() < a.y())
a = i;
}
double angles = 0,face = 180.0,maxangle=0;
Point current = a,match =null;
do{
match = null;
maxangle = 0;
p.add(current);
for(Point i:points){
if(!p.contains(i)||i==a){
if(i!=current) {
angles = Math.atan2(i.y() - current.y(), i.x() - current.x()) * 180.0 / Math.PI;
angles = 90 - face - angles;
}
if(angles<0)
angles = 360+angles;
if(angles>maxangle||(angles==maxangle)&&(match==null|| (Math.pow(i.x()-current.x(),2)+Math.pow(i.y()-current.y(),2)>
(Math.pow(match.x()-current.x(),2)+Math.pow(match.y()-current.y(),2))))){
match = i;
maxangle = angles;
}
}
}
if (match!=null)
current = match;
face = (face+maxangle)%360;
}while (current!=a&&match!=null);
return p;
}
}
class Point{
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public int x() {
return x;
}
public int y() {
return y;
}
}