図面の簡単なポリゴン(ソート角度によって順不同ポイントからシンプルなポリゴンを作成します)

キーワード:極角は、単純なポリゴンの生成をソート

平面内の点の集合を考えると、あなたのタスクは、ポイントを使用してポリゴンを描画することです。あなたはすべてのポイントを使用する必要があります。具体的には、セットの各点は、多角形の頂点である必要があり、ポリゴンは、他の頂点を持っていなければなりません。ポリゴンのどの2つの線分は、2つの連続する線分の中間頂点を除いて、一般的に任意の点を有していなくてもよいです。例えば、左側の点を考慮すると、有効なポリゴンは右側に示されています。

質問の意味:

非順序集合セット平面ポイントに、目標は、単純なポリゴンを構築することで、簡単なポリゴンポリゴン比べ制約は(被写体が特定の記述を有する)項ポリゴン無限の自家受粉に定義されています。

分析:

ポリゴンとしてシーケンス内の任意のポイント。単純なポリゴンの制約を満たす配列に対応する特定の元の配列に結果をソートコンパレータは、自己元のシーケンスと見ることができます。ここではそのユニバーサル配列ソートアルゴリズムによって適用することができ、望ましい結果を与えるために、コンパレータがある意味するかもしれません。

答えは、極角の一種である古典的なグラハムスキャンアルゴリズムの問​​題に対して、プリソートサブ標準凸包アルゴリズムです。極角は、共通の軸に基づく一種の古典的なアイデアを発注点の二次元セットの一種であるグラハムスキャンスキャンはポールのどの部分を直接扱うことができますが、単純なポリゴンとして、あるいは特殊なケースの無限大で小修理の後に見ることができます点の軸基づいてソート順序を処理します。この時点で、直感的な指導のいくつかの種類があります:シンプルなポリゴン構造的な問題は、グラハムスキャンマイクロレタッチプリソートすることによって解決することができます。

特別なマルチ共線点(点極)プロセス定義をソート極角を追加する必要があり、グラハム・スキャンは、スキャンを達成するために、遅延にマルチ同一直線上の点を扱うことができます。多重共線点が増加する直径の補足部分配列順序を電極として定義され、特別な場合は、隣接する共通電極線間隔の方向である配列を減速。

なぜインポッシブル?すべてのポイントが同じ行にあります。

コード:

#include <iostream>
#include <array>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;

namespace cglib {
    template <class Type = int>
    struct Vec2{
        Type x, y;
        Vec2(){}
        Vec2(Type _x, Type _y): x(_x), y(_y){}
        bool operator < (const Vec2& rhs) {
            return y == rhs.y ?  x < rhs.x : y < rhs.y;
        }

        Vec2 operator - (const Vec2& rhs) const {
            return Vec2(rhs.x - x, rhs.y - y);
        }

        double length2() const {
            return x * x + y * y;
        }
    };
    using vec2i = Vec2<int>;

    template <class Type>
    int to_left_test(const Type p, const Type q, const Type s) {
        int x = _Area(p, q, s);
        return  x == 0 ? -1: x > 0;
    }

    template <class Type>
    int _Area(const Type& p, const Type& q, const Type& s) {
        return p.x * q.y - p.y * q.x +
               q.x * s.y - q.y * s.x +
               s.x * p.y - s.y * p.x;
    }

    bool graham_presort(std::vector<vec2i>& P, std::vector<int>& idx) {
        std::swap(idx[0], idx[std::min_element(P.begin(), P.end())-P.begin()]);

        bool is_same_line = true;
        std::sort(idx.begin()+1, idx.end(), [&](const int& lhs, const int& rhs)->bool{
            switch (to_left_test(P[idx[0]], P[lhs], P[rhs])) {
                case -1:
                    return (P[lhs]-P[idx[0]]).length2() < (P[rhs]-P[idx[0]]).length2();
                case 0:
                    is_same_line = false;
                    return false;
                case 1:
                    is_same_line = false;
                    return true;
            }
        });
        if(!is_same_line) {
            for(int i = idx.size()-2; i > 0; i--) {
                if(to_left_test(P[idx[0]], P[*idx.rbegin()], P[idx[i]]) == -1) continue;
                std::reverse(idx.begin()+i+1, idx.end());
                break;
            }
        }
        return !is_same_line;
    }
}


int main() {
    using namespace cglib;
    int T, N;

    std::cin >> T;
    for(int t = 0; t < T; t++) {
        std::cin >> N;
        std::vector<vec2i> P;
        vec2i p;
        for(int i = 0; i < N; i++) {
            std::cin >> p.x >> p.y;
            P.emplace_back(p);
        }
        std::vector<int> idx(P.size());
        for(int i = 0; i < idx.size(); i++) idx[i] = i;

        std::cout << "Case " << t+1 << ":" << std::endl;
        if( !graham_presort(P, idx) ) {
            std::cout << "Impossible\n";
        }
        else {
            for(int i = 0; i < idx.size()-1; i++)
                std::cout << idx[i] << ' ';
            std::cout << *idx.rbegin() << std::endl;
        }

    }
}

おすすめ

転載: www.cnblogs.com/xiconxi/p/11201543.html