zoukankan      html  css  js  c++  java
  • 2015 北京网络赛 E Border Length hihoCoder 1231 树状数组 (2015-11-05 09:30)

    #1231 : Border Length

    时间限制:1000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    Garlic-Counting Chicken is a special species living around the Lake of Peking University.

    A Garlic-Counting Chicken always flies out from home in the morning, goes to some fixed points looking for buuugs(a kind of worm), and comes back home in the afternoon.

    Students from the School of Life Sciences find that, a Garlic-Counting Chicken always flies a straight line between two points, and its trace never goes across itself. The students want to find out the relationship between Garlic-Counting Chicken and the Lake. So they ask you to calculate the length of border of the common area between the Lake and one Garlic-Counting Chicken's daily trace.

    输入

    There are no more than 10 test cases.

    For each test case, the first line contains n, the number of points on the trace in order. 1<=n<=1000.

    Then n lines follow. Each line is a pair of integer x, y representing the n points' coordinates in order.

    The last line contains three integers x,y and r  descripting the Lake, The Lake is a circle. Its center is at (x,y) and its radius is r.  

    The input ends if n = 0.

    All |x|, |y|, |r| are smaller than 107.

    输出

    For each test case, output the length of the border of the common area. Please round the answer to the closest integer.

    样例输入
    4
    -10 -10
    -10 10
    10 10
    10 -10
    -10 -10 20
    4
    -10 -10
    -10 10
    10 10
    10 -10
    -10 -10 4
    4
    -10 -10
    -10 10
    10 10
    10 -10
    0 0 10
    4
    -40 -40
    -40 40
    40 40
    40 -40
    0 0 50
    0
    样例输出
    71
    14
    63
    297
    这样比较 好写,也好理解,但是还是写了挺长的代码
    #include <iostream>
    #include <algorithm>
    #include <string.h>
    #include <math.h>
    #include <cstdio>
    using namespace std;
    const double eps=0.000000000001;
    const double PI=acos(-1.0);
    const int maxn=3005;
    int dcmp(double a)
    {
        if(fabs(a)<eps)return 0;
        else return a>0?1:-1;
    }
    struct Point
    {
      double x,y;
      Point(double cx=0,double cy=0)
      {
          x=cx; y=cy;
      }
      double ang;
      void Angle()
      {
          ang=atan2(y,x);
          if(ang<0){
            ang+=2*PI;
          }
      }
      bool operator <(const Point &rhs)const
      {
         return ang<rhs.ang;
      }
    };
    struct Circle
    {
        Point c;
        double r;
        Circle(Point cc=Point(0,0),double cr=0)
        {
            c=cc; r=cr;
        }
        Point point(double a)
        {
            return Point(c.x+cos(a)*r, c.y+sin(a)*r);
        }
    };
    Point operator -(Point A, Point B)
    {
        return Point(A.x-B.x,A.y-B.y);
    }
    Point operator +(Point A, Point B)
    {
        return Point(A.x+B.x,A.y+B.y);
    }
    bool operator ==(const Point &A, const Point &B)
    {
        return dcmp(A.x-B.x) == 0&& dcmp(A.y-B.y)==0;
    }
    double Dot(Point A,Point B)
    {
        return A.x*B.x+A.y*B.y;
    }
    double Length(Point A)
    {
         return sqrt(Dot(A,A));
    }
    double Cross(Point A, Point B)
    {
        return A.x*B.y - A.y*B.x;
    }
    Point TE[maxn];
    Circle C;
    struct Ins{
      Point c;
      int id;
    }Poi[maxn];
    struct Line
    {
        Point p;
        Point v;
        Line(Point cp=Point(0,0),Point cv=Point(0,0))
        {
            p=cp; v=cv;
        }
        Point point(double a)
        {
            Point te=Point(v.x*a,v.y*a);
            return p+te;
        }
    };
    int getLineCicleIntersection(Line L,Circle C, double &t1,double &t2,Point &A,Point &B)
    {
        double a=L.v.x,
               b=L.p.x-C.c.x,
               c=L.v.y,
               d=L.p.y-C.c.y;
        double e=a*a+c*c,
               f=2*(a*b+c*d),
               g=b*b+d*d-C.r*C.r;
        double delta=f*f-4*e*g;
        if(dcmp(delta)<0)return 0;
        if(dcmp(delta)==0)
        {
            t1=t2=-f/(2*e);A=L.point(t1);
            return 1;
        }
        t1=(-f - sqrt(delta))/(2*e);
        A=L.point(t1);
        t2=(-f + sqrt(delta))/(2*e);
        B=L.point(t2);
        return 2;
    }
    int judjiaodian(int n)
    {
         int nu=0;
         double t1,t2;
         Point A,B;
         for(int i=0; i<n; i++)
         {
             int ge=getLineCicleIntersection(Line(TE[i],TE[i+1]-TE[i]),C,t1,t2,A,B);//计算直线和圆交点 大白书模板
               if(ge==0)continue;
               double s=Length(TE[i]-TE[i+1]);
               double d1=Length(TE[i]-A);
               double d2=Length(TE[i+1]-A);
              if(ge==1){
                 if(dcmp(s-d1)>=0&&dcmp(s-d2)>=0) //判断是否在这条边上
                 {
                       Poi[nu].c=A; Poi[nu].id=i; nu++;
                 }
                continue;
              }
              double d3=Length(TE[i]-B);
              double d4=Length(TE[i+1]-B);
              if(dcmp(s-d1)>=0&&dcmp(s-d2)>=0&&dcmp(s-d3)>=0&&dcmp(s-d4)>=0)//如果存在两个点
                {
                     if(d1>d3){//应该把离起点进的点放在前面
                        swap(A,B);
                     }
                     Poi[nu].c=A; Poi[nu].id=i;nu++;
                     Poi[nu].c=B; Poi[nu].id=i;nu++;
                }else if(dcmp(s-d1)>=0&&dcmp(s-d2)>=0)
                {
                     Poi[nu].c=A; Poi[nu].id=i;nu++;
                }else if(dcmp(s-d3)>=0&&dcmp(s-d4)>=0)
                {
                     Poi[nu].c=B; Poi[nu].id=i;nu++;
                }
         }
         int ge=1;
         for(int i=1; i<nu; i++)
            if( (Poi[i].c==Poi[ge-1].c) == false )
             Poi[ge++]=Poi[i];
         nu=ge;
         return nu;
    }
    int isPointInpolygon(Point p,int n)//判断点是否在多边形内
    {
        int wn=0;
        for(int i=0; i<n; i++)
        {
            int k=dcmp(Cross(TE[i+1]-TE[i],p-TE[i]));
            int d1=dcmp(TE[i].y -p.y );
            int d2=dcmp(TE[i+1].y-p.y);
            if( k > 0 && d1 <= 0 && d2 > 0 )wn++;
            if( k < 0 && d2 <= 0 && d1 >0  )wn--;
         }
         if(wn!=0)return 1;
         return 0;
    }
    void solve(int n)
    {
        int numOfInCir=0;
        double dist=0;
        for(int i=0; i<n; i++)
            {
                if( dcmp( C.r-Length(TE[i]-C.c) )>=0 )numOfInCir++;
                dist+=Length( TE[i+1]-TE[i] );
            }
        if(isPointInpolygon(C.c,n))
        {
            if(numOfInCir==n){
                printf("%.0lf
    ",dist);
            }else printf("%.0lf
    ",PI*2*C.r);
            return;
        }
        if(numOfInCir == n)
        {
                printf("%.0lf
    ",dist);
        }else printf("0
    ");
    }
    Point Hu[maxn];
    double judsolveCir(int nu,int n)
    {
        for(int i=0; i<nu; i++)
        {
            Hu[i]=Poi[i].c-C.c;
            Hu[i].Angle();
        }
        sort(Hu,Hu+nu);
        Hu[nu]=Hu[0];
        Hu[nu].ang+=2*PI;
        double ans=0;
        for(int i=0; i<nu; i++)
        {
            double ang=(Hu[i].ang+Hu[i+1].ang)/2;
            if(ang>2*PI)ang-=2*PI;
            Point t =C.point(ang);
            if(isPointInpolygon(t,n))
            {
               ang=Hu[i+1].ang-Hu[i].ang;
               ans+=ang*C.r;
            }
        }
        return ans;
    }
    Point TP[maxn];
    double judsolvePoly(int nu, int n)
    {
       int loc=0,num=0;
       for(int i=0; i<n; i++)//融合那些点
       {
           TP[num++]=TE[i];
           while(loc<nu&&Poi[loc].id<=i){
             TP[num++]=Poi[loc].c; loc++;
           }
       }
       loc=1;
       for(int i=1; i<num; i++)
        if((TP[i]==TP[loc-1])==false )TP[loc++]=TP[i];
       num=loc;
       TP[num]=TP[0];
       double ans=0;
       for(int i=0; i<num; i++)
       {
           Point tt=TP[i]+TP[i+1];
           tt.x*=0.5;
           tt.y*=0.5;
           double d1=Length(C.c-tt);
           if(dcmp(C.r-d1)>=0){
             ans+=Length(TP[i+1]-TP[i]);
           }
       }
       return ans;
    }
    int main()
    {
        int n;
        while(scanf("%d",&n)==1&&n)
        {
            for(int i=0; i<n; i++)
                scanf("%lf%lf",&TE[i].x,&TE[i].y);
                TE[n]=TE[0];
            scanf("%lf%lf%lf",&C.c.x,&C.c.y,&C.r);
            int nu=judjiaodian(n);//计算交点
            if(nu==0||nu==1){
               solve(n);// 特判那几种情况
               continue;
            }
            double ans=judsolveCir(nu,n);// 计算圆在多边形内的部分
            ans+=judsolvePoly(nu,n);// 计算多边形在圆内的部分
            printf("%.0lf
    ",ans);
        }
        return 0;
    }
    View Code
     

    题意:

  • 相关阅读:
    使用ansible实现批量免密认证
    python自如爬虫
    python批量发邮件
    诸葛亮诫子书
    CSS3阴影 box-shadow的使用和技巧总结
    js必须掌握的基础
    心态不好,你将永远是个弱者!
    Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
    xampp的安装和配置
    css3动画
  • 原文地址:https://www.cnblogs.com/Opaser/p/4941080.html
Copyright © 2011-2022 走看看