ACM - Псков

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » ACM - Псков » Геометрия » Выпуклая оболочка


Выпуклая оболочка

Сообщений 1 страница 3 из 3

1

Выпуклая оболочка множества точек на плоскости. Функция возвращает вектор всех точек, попавших в оболочку. Этот алгоритм описан в книге Меньшикова  в разборе задачи 5D.

Код:
struct Point{
     double x, y;
     bool operator < (const Point& p){
          return y<p.y || (y==p.y && x<p.x);
     }
};


vector <Point> convexHull (vector<Point>& arr){
        int start=0;

        if(arr.size()<3)
            return vector<Point>();

        vector<Point> conv;

        int end=0;
        for (int i=1; i<arr.size(); ++i){
            if(arr[i] < arr[start]){
                start = i;
            }
        }

        int p=start;
        double dx=1.0;
        double dy=0;
        conv.push_back(arr[start]);
        
        do{
            double coss = -2.0;
            double len = 0;

            int next = -1;
            for (int i=0; i<arr.length; ++i){
                double sp = dx*(arr[i].x-arr[p].x) + dy*(arr[i].y-arr[p].y);
                double leng = sqrt((arr[i].x-arr[p].x)*(arr[i].x-arr[p].x)+(arr[i].y-arr[p].y)*(arr[i].y-arr[p].y));
                if(leng>1e-8){
                    double ccos=sp/leng;
                    if(ccos>coss){
                        next=i;
                        coss=ccos;
                        len=leng;
                    }
                }
            }

            if(next==-1)
                return vector<Point>();

            conv.push_back(arr[next]);
            dx=(arr[next].x-arr[p].x)/len;
            dy=(arr[next].y-arr[p].y)/len;
            p=next;
        }while(p!=start);

        return conv;
}

2

А прокомментировать? где что делается, где что хранится? :dontknow:

3

Похоже на алгоритм Джарвиса (заворачивания подарка).
Строим выпуклую оболочку постепенно, точка за точкой. Сначала добавляем самую левую нижнюю точку (она точно войдёт в оболочку).
Теперь сама итерация. Т.е. какой-то кусок уже построен, пытаемся найти следующую точку. Чем следующая точка так отличается от остальных? Тем, что если мы встанем в последнюю точку выпуклой оболочки, продолжим мысленно последнюю сторону, то полярный угол следующей точки относительно направления прямой будет ближе остальных.
Т.е. в качестве следующей точки выбираем ту, которая по полярному углу ближе всех к направлению последней стороны. Вспоминая геометрию, это значит, что косинус угла должен быть как можно больше. А косинус считается по скалярному произведению (делённому на длины сторон треугольника).

Работает алгоритм за O (N H), где H - количество точек в искомой оболочке. На обычных задачах это не очень хорошо (если H=N, то будет N^2 супротив NlogN у Грэхэма), но в специфических случаях, когда известно, что H маленькое, работает даже быстрее.


Вы здесь » ACM - Псков » Геометрия » Выпуклая оболочка