HDU 3814 Signal Coverage

來源:互聯網
上載者:User

給一條直線和多個簡單多邊形,求在多邊形內(包括邊上)的線段長度佔總長度的百分比。

 

WA了一晚上和一上午換了N種方法終於想到了個簡單又好寫不用各種討論無視各種trick的方法。

核心思想就是把線段根據交點分成若干段,然後判斷每段的某一邊是否有面積。

那這個怎麼判斷呢?

如:不告訴你具體的多邊形情況,只知道多邊形的邊與線段相交的情況,能判斷出哪些是地區是多邊形內,哪些是外面的嗎?

很簡單的啦,交替就行了,如:

具體做法麼就是把交點都求出來,並記錄這個交點線上段的兩邊各產生了幾條線(多邊形的邊的某個端點線上段上會在某一邊產生一條線,普通的相交會在兩邊都產生線,重合的就無視掉吧),排個序,相同的點都合并起來。

求長度麼就是掃一遍,看到目前這個點為止線上段的兩邊各已出現多少線,只要有一邊是奇數個,那接下去的一段地區就在某個多邊形內了。

那線段的起點是否在多邊形內呢?反向延長到足夠遠處,從哪裡開始一路判斷過來就好了。

 

 

 

#include<iostream>#include<algorithm>#include<cmath>#define eps 1e-9using namespace std;double f_abs(double x){    return x<0?-x:x;}struct Point{    double x,y;    bool up,dn;    void disp(){        printf("%lf %lf\n",x,y);    }    void get(){        scanf("%lf%lf",&x,&y);    }    bool friend operator<(Point a,Point b){        if(f_abs(a.x-b.x)<eps)return a.y<b.y;        return a.x<b.x;    }    bool friend operator>(Point a,Point b){        return b<a;    }    bool friend operator==(Point a,Point b){        return f_abs(a.x-b.x)<eps&&f_abs(a.y-b.y)<eps;    }};struct Line{    Point s,e;    bool friend operator<(Line a,Line b){        return a.s<b.s;    }    void st(){        Point t;        if(s>e){            t=s;s=e;e=t;        }    }    void get(){        s.get();e.get();        st();    }};Line line[200000],myl[2];Point ep[200000];int en;double get_cross(Point a,Line b){    double ax,ay,bx,by;    ax=b.s.x-a.x;    ay=b.s.y-a.y;    bx=b.e.x-a.x;    by=b.e.y-a.y;    return ax*by-ay*bx;}int inter(Line a,Line b,Point &rp=Point()){//0:不相交 1:相交 2、3:端點相交,a在b某一邊 4:重合    double cj[2];    cj[0]=get_cross(b.s,a);cj[1]=get_cross(b.e,a);    if(cj[0]*cj[1]>eps)return 0;    cj[0]=get_cross(a.s,b);cj[1]=get_cross(a.e,b);    if(cj[0]*cj[1]>eps)return 0;    if(f_abs(cj[0])<eps&&f_abs(cj[1])<eps){        return 4;    }    if(f_abs(cj[0])<eps){        rp=a.s;        if(cj[1]>eps)return 2;        else return 3;    }else if(f_abs(cj[1])<eps){        rp=a.e;        if(cj[0]>eps)return 2;        else return 3;    }else{        double key1=(a.e.x-a.s.x)*(b.e.y-b.s.y);          double key2=(b.e.x-b.s.x)*(a.e.y-a.s.y);          double key=key1-key2;          rp.x=(a.s.y-b.s.y)*(a.e.x-a.s.x)*(b.e.x-b.s.x);          rp.x-=key2*a.s.x-key1*b.s.x;          rp.x/=key;          if(f_abs(b.e.x-b.s.x)<eps)rp.y=(a.e.y-a.s.y)/(a.e.x-a.s.x)*(rp.x-a.s.x)+a.s.y;          else rp.y=(b.e.y-b.s.y)/(b.e.x-b.s.x)*(rp.x-b.s.x)+b.s.y;          return 1;    }}int ln;void get_myl2(){    double dy=myl[0].e.y-myl[0].s.y,dx=myl[0].e.x-myl[0].s.x;    double t=sqrt(dy*dy+dx*dx);    dy/=t;dx/=t;    myl[1].e=myl[0].s;    myl[1].s.x=myl[1].e.x-300000*dx;    myl[1].s.y=myl[1].e.y-300000*dy;}void get_data(){    myl[0].get();    int t,n,i;    int pcnt=0;    Point p[2],ini;    ln=0;    scanf("%d",&t);    while(t--){        scanf("%d",&n);        ini.get();        if(n==1)continue;        p[0]=ini;        bool f=0;        for(i=1;i<n;i++){            f^=1;            p[f].get();            line[ln].s=p[f^1];            line[ln].e=p[f];            line[ln++].st();        }        line[ln].s=p[f];        line[ln].e=ini;        line[ln++].st();    }    get_myl2();}double get_len(Point a,Point b){    return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y));}void get_ep(Line l){    en=0;    int t,i;    for(i=0;i<ln;i++){        t=inter(line[i],l,ep[en]);        if(!t||t==4)continue;        if(t==1){            ep[en].up=1;            ep[en++].dn=1;        }else if(t==2){            ep[en].up=1;            ep[en++].dn=0;        }else{            ep[en].up=0;            ep[en++].dn=1;        }    }    sort(ep,ep+en);    int ten=0;    for(i=0;i<en;i++){        if(ten&&ep[i]==ep[ten-1]){            ep[ten-1].up^=ep[i].up;            ep[ten-1].dn^=ep[i].dn;        }else ep[ten++]=ep[i];    }    en=ten;}void run(){    if(myl[0].s==myl[0].e){        printf("0.00%%\n");        return;    }    int i;    bool in=0,left=0,right=0;    get_ep(myl[1]);    for(i=0;i<en;i++){left^=ep[i].up;right^=ep[i].dn;    }if(left||right)in=1;else in=0;    get_ep(myl[0]);    double len=get_len(myl[0].s,myl[0].e),res=0;    Point lp=myl[0].s;    ep[en++]=myl[0].e;    for(i=0;i<en;i++){        if(ep[i]==myl[0].s)continue;        if(in)res+=get_len(ep[i],lp);left^=ep[i].up;right^=ep[i].dn;        if(left||right)in=1;else in=0;        lp=ep[i];    }    printf("%.2lf%%\n",res*100/len);}int main(){    int i,t;    scanf("%d",&t);    for(i=1;i<=t;i++){        get_data();        printf("Case %d: ",i);        run();    }    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.