1. 程式人生 > >蠻力法在求解凸包問題中的應用(JAVA)

蠻力法在求解凸包問題中的應用(JAVA)

凸包問題向來是計算幾何中最重要的問題之一,許多各式各樣的應用大多要麼本身就是圖凸包問題要麼其中一部分需要按照凸包問題解決。

凸集合定義:對於平面上一個點集合,如果集合中的任意兩點p和q為端點的線段都屬於該集合,那麼稱這個集合為凸集合。

凸包定義:一個點集合S的凸包是包含S的最小凸集合。我們可以假設有一塊板子,板子上面有許多釘子,用一根橡皮筋將所有的釘子都圍住,凸包就是以橡皮筋圈為邊界的區域。


在座標平面上穿過兩個點(x1, x2),(x2, y2)的直線方程為  ax+by = c (其中a = y2- y1, b = x1 - x2, c = x1y2 - y1x2)

由兩個點連起來的直線會將平面分成兩部分,其中半個平面的點都滿足ax+by>c ,另一半平面中的點都滿足ax+by<c ,對於線上的點來說滿足ax+by=c。因此,演算法的思路就是對於每個點帶入ax+by-c,判斷表示式結果的符號是否相同即可。

import java.util.*;

class Point {
    int x;
    int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public String toString() {
        return "Point{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
}
public class Main {
    public static void main(String[] args) {
        Point[] points = new Point[6];
        List arr = new ArrayList();
        points[0] = new Point(1,3);
        points[1] = new Point(2,1);
        points[2] = new Point(3,5);
        points[3] = new Point(4,4);
        points[4] = new Point(5,2);
        points[5] = new Point(3,2);
        arr = outerTrees(points);
        Iterator it = arr.iterator();
        while (it.hasNext()) {
            System.out.println(it.next().toString() + " ");
        }
    }
    private static List<Point> outerTrees(Point[] points) {
        Set<Point> ans = new HashSet<>();
        /**
         * 只有一個點
         * */
        if (points.length == 1){
            ans.add(points[0]);
            return new ArrayList<>(ans);
        }

        for (int i = 0; i < points.length-1; i++){
            for (int j = i + 1; j < points.length; j++){
                int oneSide = 0;
                for (int k = 0; k < points.length; k++){
                    if (k == i || k == j) {
                        continue;
                    }
                    if (calcuTriangle(points[i], points[j], points[k]) > 0){
                        oneSide++;
                    }
                }
                if (oneSide == points.length-2 || oneSide == 0){
                    ans.add(points[i]);
                    ans.add(points[j]);
                }

                int otherSide = 0;
                for (int k = 0; k < points.length; k++){
                    if (k == i || k == j) continue;
                    if (calcuTriangle(points[i], points[j], points[k]) < 0){
                        otherSide++;
                    }
                }
                if (otherSide == points.length-2 || otherSide == 0){
                    ans.add(points[i]);
                    ans.add(points[j]);
                }
            }
        }

        return new ArrayList<>(ans);
    }
    private static int calcuTriangle(Point a1, Point a2, Point a3) {
        return a1.x * a2.y + a3.x * a1.y + a2.x * a3.y - a3.x * a2.y - a2.x * a1.y - a1.x * a3.y;
    }
}