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
     

    题意:

  • 相关阅读:
    python网络爬虫与信息提取——5.信息组织与提取方法
    python网络爬虫与信息提取——4.Beautiful Soup库入门
    python网络爬虫与信息提取——3.requests爬虫实战
    python网络爬虫与信息提取——2.网络爬虫排除标准robots
    python网络爬虫与信息提取——1.requests库入门
    时间戳转日期
    splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目
    数组、对象等的按值传递与数字、字符串不同
    用flex做垂直居中
    手机端页面自适应解决方案-rem布局
  • 原文地址:https://www.cnblogs.com/Opaser/p/4941080.html
Copyright © 2011-2022 走看看