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
     

    题意:

  • 相关阅读:
    Martin Fowler关于IOC和DI的文章(原版)
    父类引用指向子类对象详解
    求中位数总结
    二叉树的遍历方法
    MySQL知识小结
    栈和队列的基础算法学习(EPI)
    链表的基础题目学习(EPI)
    数组和字符串的基础题目学习(EPI)
    基本类型算法题目学习(EPI)
    被C语言操作符优先级坑了
  • 原文地址:https://www.cnblogs.com/Opaser/p/4941080.html
Copyright © 2011-2022 走看看