半平面,指的就是一條直線把乙個平面分成了兩個半平面…… 如果有好幾條這樣的直線,就會有很多個半平面,我們有的時候會求他們的交。
半平面交乙個很有用的用處是求多邊形的核。所謂多邊形的核,就是指多邊形中的一塊區域,在這個區域裡面放乙個燈泡,這個燈泡轉一周,能照亮這個多邊形裡所有的地方。稍微想想就會知道,凸多邊形一定是有核的,而且就是它本身,但是凹多邊形就未必有核了。比如這個多邊形
藍色的區域就是它的核,但是如果你站在淡黃色點的話,叉子的那一部分你就看不到了。
怎麼求乙個多邊形的核呢?有這樣乙個演算法:
1. 將所有點逆時針/順時針排序,到底是逆時針還是順時針很關鍵,影響到後面符號的判斷。
2. 維護乙個點集合kernel,這個點集合所包含的點就是這個多邊形的核;
3. 對於原多邊形的每條邊構成的直線line,掃一下所有的點,如果點i就在對於這條線而言的多邊形內部,那麼點i直接就加入kernel集合;
否則,考慮點i旁邊的兩個點i+1, i-1, 對每個點判斷,如果它在對現在直線line而言的多邊形內部,那麼乙個在外部的點i和乙個在內部的點j必然會與現在這條直線相交,相交的點加入kernel;
這裡,如何判斷「乙個點對一條直線而言,是在多邊形的內部還是外部」呢?
對於p1p2兩點構成的直線,我們用這個函式將其寫成ax + by + c = 0的形式:
void get_equation(point p1,point p2,double &a,double &b,double &c)
然後,將當前點代入ax + by + c,如果是順時針排的,則如果結果大於0,就是在內部,如果是逆時針排的,結果小於0即是在內部。
4. 最後留在kernel集合內的點,就是我們要求的核的邊界點。
這個演算法的道理其實就是半平面交,因為對於每一條邊而言,它的「多邊形內部」就是乙個半平面,比如乙個正方形abcd,對ab邊所在直線而言,只有一邊是在多邊形內的,當然也只有從這個區域才能看見ab邊。所以演算法實際上求的就是多邊形內部能看到每條邊的區域的交。
我們可以用「凹」字模擬一下這個演算法:
把8個點這麼編號,這裡是按照逆時針編號的。
首先,看12所在直線,顯然對於12而言,所有點都在他的內部,於是kernel = 所有點;
之後看23,對23而言,恰好在其直線上和在其下方的點是在他的內部,同樣kernel = 所有點;
看34, 就不一樣了。顯然5678都不在對他而言的多邊形的內部,因為能看到34的多邊形區域是
之後便按個檢查,下方那個點是在檢查8點時,發現1點(8號點相鄰的點)在內部,於是1-8 和 3-4 交點入kernel。
現在kernel是1234x, x是新來的交點。
之後檢查45,你會發現藍色區域又變小了(懶得畫了,變到只剩下右下角了),然後檢查56的時候,就沒有了。於是我們知道這個圖形沒有核。
演算法複雜度是n平方的,聽說有nlgn做法,不過這個n平方的我就想了半天……
貼個**吧
#include#include#include#include#include#define d(x) cout<
return 1;
return -1;
}struct point
; point(double _x, double _y)
point operator +(const point &b) const
point operator -(const point &b) const
double operator ^(const point &b) const };
point ori_point[110]; // origin set
point point[110]; // kernel set
int p_point=0;
void getline(point p1, point p2, double &a, double &b, double &c)
point intersection(point p1,point p2,double a,double b,double c)
point tp[110];
void cut(double a, double b, double c, point p, int &cnt)
if( sgn (a*p[i+1].x + b*p[i+1].y + c) < 0)
tp[++tmp] = intersection(p[i],p[i+1],a,b,c);
} }
for(int i = 1;i <= tmp;i++)
p[0] = p[tmp];
p[tmp+1] = p[1];
cnt = tmp;
}int n;
int t;
void init()
int main()
point[n+1] = point[1];
point[0] = point[n];
memcpy(ori_point, point, sizeof(point));
p_point = n;
for(i=1;i<=n; i++)
if(p_point>0)
printf("yes\n");
else
printf("no\n");
} system("pause");
return 0;
}
bzoj2618 凸多邊形 半平面交
bzoj上300題辣!啦啦啦上圖紀念!本來bzoj2618打算第299個做的,然後日常翻題解的時候發現popoqqq居然是第300題做的bzoj2618!為了和大爺同步我就先水另外一題,然後也在第300題a可bzoj2618!和大爺的300題一樣是不是有什麼含義 難道是乙個flag?多個凸多邊形求交...
POJ 3335 判斷乙個多邊形是否存在核
什麼是多邊形的核呢 多邊形的核是乙個點的集合,在這個集合裡面的所有的點與多邊形上所有的點的連線都在多邊形的內部。就是說從這個點可以看到多邊形上所有的點。多邊形的核應該怎麼求呢 首先有乙個結論就是 能看到一條完整直線的點分布在直線的一側,這樣的話我們就可以求所有線段的一側 相當於直線的一側 就是看半平...
CQOI2006 凸多邊形 暴力半平面交
半平面交總覺得和線性規劃莫名的像?逆時針給出n個凸多邊形的頂點座標,求它們交的面積。例如n 2時,兩個凸多邊形如下圖 則相交部分的面積為5.233。輸入格式 第一行有乙個整數n,表示凸多邊形的個數,以下依次描述各個多邊形。第i個多邊形的第一行包含乙個整數mi,表示多邊形的邊數,以下mi行每行兩個整數...