半平面交模板

2021-09-07 05:46:15 字數 4342 閱讀 3682

妹的,一直沒有想清楚無解的情況到底是如何判斷的。

偷來乙個模板。

半平面交的結果:1.凸多邊形(後面會講解到)2.無界,因為有可能若干半平面沒有形成封閉3.直線,線段,點,空(屬於特殊情況吧)

演算法:1:根據上圖可以知道,運用給出的多邊形每相鄰兩點形成一條直線來切割原有多邊形,如果多邊形上的點i在有向直線的左邊或者在直線上即儲存起來,否則判斷此點的前乙個點i-1和後乙個點i+1是否在此直線的左邊或線上,在的話分別用點i和點i-1構成的直線與此時正在切割的直線相交求出交點,這個交點顯然也要算在切割後剩下的多邊形裡,同理點i和點i+1。原多邊形有n條邊,每條邊都要進行切割,所以時間複雜度為o(n^2)。

**實現:以 poj3130 為例,裸的模板。

#include#include

#include

#include

#include

#include

#define inf 0x7fffffff

#define exp 1e-10

#define pi 3.141592654

using

namespace

std;

const

int maxn=111

;struct

point

}an[maxn],bn[maxn],cn[maxn];

///an:記錄最開始的多邊形;bn:臨時儲存新切割的多邊形;cn:儲存新切割出的多邊形

typedef point vector;

vector

operator + (vector a,vector b)

vector

operator - (vector a,vector b)

vector

operator * (vector a,double p)

vector

operator / (vector a,double p)

int dcmp(double x)

double

cross(vector a,vector b)

double

a,b,c;

intn,m;

void getline(point a,point b)///

獲取直線 ax + by + c = 0

///getline()函式得到的直線和點a和點b所連直線的交點

point intersect(point a,point b)

void cut()///

切割,原多邊形的點為順時針儲存

}for (int i=1 ;i<=cnt ;i++) cn[i]=bn[i];

cn[0]=bn[cnt];

cn[cnt+1]=bn[1

]; m=cnt;///

新切割出的多邊形的點數

}void

solve()

}int

main()

return0;

}

view code

poj3335 ,給出兩種方法

1.o(n^2)

#include#include

#include

#include

#include

#include

#define inf 0x7fffffff

#define exp 1e-10

#define pi 3.141592654

using

namespace

std;

const

int maxn=111

;struct

point

}an[maxn],bn[maxn],cn[maxn];

typedef point vector ;

vector

operator + (vector a,vector b)

vector

operator - (vector a,vector b)

vector

operator * (vector a,double p)

vector

operator / (vector a,double p)

int dcmp(double x)

double

cross(vector a,vector b)

intn,m;

double

a,b,c;

void

getline(point a,point b)

point intersect(point a,point b)

void

cut()

}for (int i=1 ;i<=cnt ;i++) cn[i]=bn[i];

cn[0]=bn[cnt];

cn[cnt+1]=bn[1

]; m=cnt;

}void

solve()

}int

main()

return0;

}

view code

2.o(nlogn)

#include#include

#include

#include

#include

#include

#define inf 0x7fffffff

#define exp 1e-10

#define pi 3.141592654

using

namespace

std;

const

int maxn=111

;struct

point

}an[maxn];

typedef point vector;

struct

line

line (point p,vector v):p(p),v(v)

//line (point p,vector v):p(p),v(v)

friend bool

operator

<(line a,line b)

}bn[maxn];

vector

operator + (vector a,vector b)

vector

operator - (vector a,vector b)

vector

operator * (vector a,double p)

vector

operator / (vector a,double p)

int dcmp(double x)

double

cross(vector a,vector b)

bool

onleft(line l,point p)

point getintersection(line a,line b)

//point getintersection(line l1, line l2)

int halfplaneintersection(line *l,int n,point *poly)

if (first1]=getintersection(q[last-1

],q[last]);

}while (first1])) last--;

if (last-first<=1) return0;

p[last]=getintersection(q[last],q[first]);

int m=0

;

for (int i=first ;i<=last ;i++) poly[m++]=p[i];

returnm;}

void calpolygon(point *p, int n, double &area, bool &shun)

bool calcore(point *ps, int

n)int

main()

//reverse(cn,cn+n);

//for (int i=0 ;i//

//int m=halfplaneintersection(bn,n,an);

if (!calcore(cn,n)) puts("no"

);

else puts("

yes"

); }

return0;

}

練習:poj 1474 

poj 2451

poj 3525

la 2218

la 2512

uva 10084

後續:歡迎提出寶貴的意見。

模板 半平面交

考慮用射線 乙個點和乙個向量 表示它左側的半平面 那麼我們可以先按與x軸正半軸夾角 可用atan2 y,x 實現 排序,然後再用雙端佇列維護當前在交中的射線即可 之所以要用雙端佇列,是因為新插入乙個半平面時隊首和隊尾都有可能被彈出,而且要注意的是,要先彈隊尾再彈隊首 在最後,還要再用隊首的彈一些隊尾...

模板 半平面交

逆時針給出n個凸多邊形的頂點座標,求它們交的面積。例如n 2時,兩個凸多邊形如下圖 則相交部分的面積為5.233。第一行有乙個整數n,表示凸多邊形的個數,以下依次描述各個多邊形。第i個多邊形的第一行包含乙個整數mi,表示多邊形的邊數,以下mi行每行兩個整數,逆時針給出各個頂點的座標。輸出檔案僅包含乙...

半平面交總結and模板

這兩天刷了poj上幾道半平面交,對半平面交有了初步的體會,感覺半平面交還是個挺有用的知識點。半平面交主要是看的zzy的國家隊 他提出的是一種o n log n 的排序增量法。poj 3335 rotating scoreboard 題目大意 world finals 要開始了,比賽場地是乙個多邊形。...