POJ1279/ZOJ1369 Art Gallery,POJ2451 Uyuw’s Concert(半平面交求多邊形的核)

來源:互聯網
上載者:User

傳說中的半平面交……

看的是朱澤園 06 年的論文,他自創的排序增量法,n*logn 的複雜度,相當給力

PS:朱澤園為了他的論文,專門在POJ上加了一道題,就是 POJ2451 Uyuw's Concert  ,裸模板題,看完論文可以先去試試

而對於 POJ1279/ZOJ1369 Art Gallery ,來說,其實也不複雜,只是點的順序是按順時針給出的,處理時注意下就好了

再說說我的個人體會,做這個 Art Gallery 時,天真的套了模板,一直 WA ,就開始胡思亂想,是不是點需要排序啊,是不是有可能按逆時針給出啊,然後加各種判斷啊,各種處理啊,把代碼搞到 250 多行,最後還是 WA ,萬般無奈之下,加了個初始化,就 AC 了,一測試,探索資料是很仁慈的,他遠沒有我想象的那麼不厚道,只是我自已又一次沙茶了,當然某人的“提醒”也有很大作用。教訓啊,血的教訓,一定要初始化,要不自己會瞎想,一瞎想,然後再加上誤導,就會沙茶……

POJ2451 那個就不貼代碼了,就是抄的,全都是抄的,甚至連基礎的精度判斷,我都被征服了,果斷放棄了原來的,改成人家的了,好吧,我淪陷了,在那 “傾國傾城” 的 code 面前……

下面是 Art Gallery 的代碼,雖然抄襲還是很嚴重,但是好歹我也 沙茶 的 debug 了半天的……

 

#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<cmath>using namespace std;const int N = 1501;const double eps = 1e-8;const double maxl = 70000;const double pi = acos(-1.0);struct cpoint {//C++建構函式,預設預設值為(0,0)    double x, y;    cpoint(double xx = 0, double yy = 0): x(xx), y(yy) {};};int dcmp(double x) {//判斷參數的符號,負數返回-1,0返回0,正數返回1    if (x < -eps) return -1; else return x > eps;}double xmult(cpoint p0, cpoint p1, cpoint p2) { // p0p1 與 p0p2 叉積    return (p1.x - p0.x) * (p2.y - p0.y) - (p2.x - p0.x) * (p1.y - p0.y);}bool EqualPoint(cpoint a, cpoint b) {//兩點相等    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;}struct cvector {//向量    cpoint s, e;    double ang, d;};//atan (double x)弧度表示的反正切//atan2(double x,double y)弧度表示的反正切,相當於atan(x/y)void setline(double x1, double y1, double x2, double y2, cvector &v) {    v.s.x = x1; v.s.y = y1;    v.e.x = x2; v.e.y = y2;    v.ang = atan2(y2 - y1, x2 - x1);//這裡的 d 代表向量(直線)和座標軸的截距,正數表示 原點 在該向量的左邊//(這道題要求左半平面交),負號則表示 原點 在右邊    if (dcmp(x1 - x2))          // x1 > x2v.d = (x1 * y2 - x2 * y1) / fabs(x1 - x2);    else v.d = (x1 * y2 - x2 * y1) / fabs(y1 - y2);}//判向量平行bool parallel(const cvector &a, const cvector &b) {    double u = (a.e.x - a.s.x) * (b.e.y - b.s.y) - (a.e.y - a.s.y) * (b.e.x - b.s.x);    return dcmp(u) == 0;}//求兩向量(直線)交點 (兩向量不能平行或重合)cpoint CrossPoint(const cvector &a, const cvector &b) {    cpoint res;    double u = xmult(a.s, a.e, b.s), v = xmult(a.e, a.s, b.e);    res.x = (b.s.x * v + b.e.x * u) / (u + v);    res.y = (b.s.y * v + b.e.y * u) / (u + v);    return res;}//半平面交排序函數[優先順序: 1.極角 2.前面的直線在後面的左邊]static bool VecCmp(const cvector &l, const cvector &r) {    if (dcmp(l.ang - r.ang)) return l.ang < r.ang;    return l.d < r.d;}cvector deq[N]; //用於計算的雙端隊列void HalfPanelCross(cvector vec[],int n,cpoint cp[],int &m){int i,tn;sort(vec,vec+n,VecCmp);for(tn=i=1;i<n;i++){if(dcmp(vec[i].ang-vec[i-1].ang) != 0)vec[tn++]=vec[i];}n=tn;int bot=0, top=1;deq[0]=vec[0], deq[1]=vec[1];for(i=2;i<tn;i++){if(parallel(deq[top],deq[top-1]) || parallel(deq[bot],deq[bot+1]))return ;while(bot<top && dcmp(xmult(vec[i].s,vec[i].e,CrossPoint(deq[top],deq[top-1])))<0)top--;while(bot<top && dcmp(xmult(vec[i].s,vec[i].e,CrossPoint(deq[bot],deq[bot+1])))<0)bot++;deq[++top]=vec[i];}while(bot<top && dcmp(xmult(deq[bot].s,deq[bot].e,CrossPoint(deq[top],deq[top-1])))<0)top--;while(bot<top && dcmp(xmult(deq[top].s,deq[top].e,CrossPoint(deq[bot],deq[bot+1])))<0)bot++;if(top <= bot+1)return ;for(m=0,i=bot;i<top;i++)cp[m++]=CrossPoint(deq[i],deq[i+1]);if(bot<top+1)cp[m++]=CrossPoint(deq[bot],deq[top]);m=unique(cp,cp+m,EqualPoint)-cp;}double PolygonArea(cpoint p[], int n) {    if (n < 3) return 0;    double s = p[0].y * (p[n - 1].x - p[1].x);    for (int i = 1; i < n; ++i)        s += p[i].y * (p[i - 1].x - p[(i + 1) % n].x);    return fabs(s / 2); // 順時針方向s為負}int n,m;cvector v[N];cpoint cp[N];void solve(){int i,j;setline(-maxl, -maxl, maxl, -maxl, v[0]);    setline(maxl, -maxl, maxl, maxl, v[1]);    setline(maxl, maxl, -maxl, maxl, v[2]);    setline(-maxl, maxl, -maxl, -maxl, v[3]);cpoint p[N];for(i=0;i<n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);p[n]=p[0];for(j=4,i=n;i>0;i--)setline(p[i].x,p[i].y,p[i-1].x,p[i-1].y,v[j++]);n=j;HalfPanelCross(v,n,cp,m);//向量(直線)集合,長度;點集,長度printf("%.2lf\n",PolygonArea(cp,m));}int main(){int t;scanf("%d",&t);while(t--){scanf("%d",&n);memset(cp,0,sizeof(cp));memset(v,0,sizeof(v));solve();}return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.