凸包問題 Graham Scan演算法

2021-09-11 18:02:43 字數 2523 閱讀 7121

平面中取一定點a,從a點出發的一條射線am,再選定乙個長度單位和角度的正方向(通常取逆時針方向)。

對於平面內任意一點b,都可以用有序對(

這樣建立的座標系稱為極座標系,定點a稱為極點,射線am稱為極軸,

若極座標系中定點a與直角座標系的原點o重合,極座標系中的極軸為直角座標系x軸正半軸,於x軸逆時針成90°角為y正半軸,則空間中任意一點a在極座標系中座標(

簡單複習之後(畢竟中學已經學過了)開始學習graham-scan演算法。

grajam-scan是一種靈活的凸包演算法,其總時間複雜度僅為o(nlogn)。graham掃瞄法的原理是從點集中先找出乙個最左下方的點,可以證明,這個點肯定在凸包上(易證),然後以這個點為極點,將所有點根據與這個點的極角排序,並且同時使用乙個棧結構維護凸包上的點。

按照極角序依次將點與棧頂的兩個點拐向判斷:若右拐,則將當前點加入棧中;否則,將棧頂的點彈出。當遍歷完點集後,還在棧中的點就是凸包上的點,而且依次出棧可以得到從起點開始順時針旋轉的所有凸包上的點。

step1:選出x座標最小的點作為極點(x座標相同,選y最小的點)。這個點必在凸包上。

step2:將其餘點按極角排序,在極角相同的情況下比較與極點的距離,離極點比較近的優先。

step3:用乙個棧s儲存凸包上的點,先將按極角和極點排序最小的兩個點入棧。

step4:按需掃瞄每個點,檢查棧頂的前兩個元素與這個點構成的折線段是否「拐」向右側(叉積<=0)。

step5:如果滿足,則彈出棧頂元素,並返回step4再次檢查,直至不滿足。將該點入棧,並對其他點不斷執行step5操作。

step6:最終棧中的元素為凸包的頂點序列。

模板:輸入n個點,輸出這n個點所圍成的凸包,從原點開始順時針輸出凸包的頂點。

同樣兩份**,graham-scan掃瞄法和jarvis步進法。

code1-graham-scan掃瞄法:

//#pragma comment(linker, "/stack:1024000000,1024000000")

#include#include#include#include//#include#include#include#include#include#include#include#include#includeusing namespace std;

#define ll long long

#define pair pair//#define max(a,b) (a)>(b)?(a):(b)

//#define min(a,b) (a)

#define clean(a,b) memset(a,b,sizeof(a))// 水印

//std::ios::sync_with_stdio(false);

// register

const int maxn=1e3+10;

const int inf32=0x3f3f3f3f;

const ll inf64=0x3f3f3f3f3f3f3f3f;

const ll mod=1e9+7;

const double eps=1.0e-8;

const double pi=acos(-1.0);

struct point

friend point operator + (const point &a,const point &b)

friend point operator - (const point &a,const point &b)

friend double operator ^ (point a,point b)

};struct v

friend v operator + (const v &a,const v &b)

friend v operator - (const v &a,const v &b)

};struct circle

};point dots[maxn];

point stk[maxn];int top;

int n;

double distance(point a,point b)

double parellel(double key)

friend point operator + (const point &a,const point &b)

friend point operator - (const point &a,const point &b)

friend double operator ^ (point a,point b)

}p[maxn];

struct v

friend v operator + (const v &a,const v &b)

friend v operator - (const v &a,const v &b)

};int n,res[maxn],top;

int cmp(point a,point b)

void jarvis()

// cout<

poj-1873-the fortified forest,題解:

凸包問題 Graham Scan

graham scan 概述 對於凸多邊形的定義不在這裡做詳細敘述,這裡給出演算法的實現原理。step 1 找出x值最小的點的集合,從其中找出y值最小的點作為初始點 step 2 獲得新序列後,p n p 1 step 3 把p 0 p 1 p 2 放入乙個棧,從i 3迴圈到i n 1,取棧頂兩個元...

凸包 Graham Scan演算法

graham scan演算法是一種靈活的凸包演算法,時間複雜度是o nlogn 演算法細節 1.選出最左下角的點 排序 x最小,其次是y最小 2.其餘點按極角排序,在極角相等的情況下距離極點 p 0 最近的優先 3.用乙個棧 陣列 儲存凸包上的點,先把p 0 p 1 壓入棧。4.掃瞄每乙個點,用叉積...

Graham Scan凸包演算法

一 什麼是凸包 在乙個二維座標系中,有若干點雜亂排列著,將最外層的點連線起來構成的凸多邊型,它能包含給定的所有的點,這個多邊形就是凸包。尋找凸包的演算法有很多種,graham scan 演算法是一種十分簡單高效的二維凸包演算法,能夠在 o nlogn 的時間內找到凸包。二 graham scan 演...