zoukankan      html  css  js  c++  java
  • hdu 2892 area

    area

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 717    Accepted Submission(s): 280

    Problem Description
    小白最近被空军特招为飞行员,参与一项实战演习。演习的内容是轰炸某个岛屿。。。 作为一名优秀的飞行员,任务是必须要完成的,当然,凭借小白出色的操作,顺利地将炸弹投到了岛上某个位置,可是长官更关心的是,小白投掷的炸弹到底摧毁了岛上多大的区域? 岛是一个不规则的多边形,而炸弹的爆炸半径为R。 小白只知道自己在(x,y,h)的空间坐标处以(x1,y1,0)的速度水平飞行时投下的炸弹,请你计算出小白所摧毁的岛屿的面积有多大. 重力加速度G = 10.
     
    Input
    首先输入三个数代表小白投弹的坐标(x,y,h); 然后输入两个数代表飞机当前的速度(x1, y1); 接着输入炸弹的爆炸半径R; 再输入一个数n,代表岛屿由n个点组成; 最后输入n行,每行输入一个(x',y')坐标,代表岛屿的顶点(按顺势针或者逆时针给出)。(3<= n < 100000)
     
    Output
    输出一个两位小数,表示实际轰炸到的岛屿的面积。
     
    Sample Input
    0 0 2000
    100 0
    100
    4
    1900 100
    2000 100
    2000 -100
    1900 -100
     
    Sample Output
    15707.96
     
    多边形与圆交
    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    typedef long long LL;
    
    const double PI = acos(-1.0);
    const double EPS = 1e-8;
    
    inline int sgn(double x) {
        return (x > EPS) - (x < -EPS);
    }
    
    struct Point {
        double x, y;
        Point() {}
        Point(double x, double y): x(x), y(y) {}
        void read() {
            scanf("%lf%lf", &x, &y);
        }
        double angle() {
            return atan2(y, x);
        }
        Point operator + (const Point &rhs) const {
            return Point(x + rhs.x, y + rhs.y);
        }
        Point operator - (const Point &rhs) const {
            return Point(x - rhs.x, y - rhs.y);
        }
        Point operator * (double t) const {
            return Point(x * t, y * t);
        }
        Point operator / (double t) const {
            return Point(x / t, y / t);
        }
        double operator *(const Point &b)const
        {
            return x*b.x + y*b.y;
        }
        double length() const {
            return sqrt(x * x + y * y);
        }
        Point unit() const {            //单位向量
            double l = length();
            return Point(x / l, y / l);
        }
    };
    double cross(const Point &a, const Point &b) {
        return a.x * b.y - a.y * b.x;
    }
    double sqr(double x) {
        return x * x;
    }
    double dist(const Point &p1, const Point &p2) {
        return (p1 - p2).length();
    }
    double sdist(Point a,Point b){
        return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
    }
    //向量 op 逆时针旋转 angle
    Point rotate(const Point &p, double angle, const Point &o = Point(0, 0)) {
        Point t = p - o;
        double x = t.x * cos(angle) - t.y * sin(angle);
        double y = t.y * cos(angle) + t.x * sin(angle);
        return Point(x, y) + o;
    }
    Point line_inter(Point A,Point B,Point C,Point D){ //直线相交交点
            Point ans;
            double a1=A.y-B.y;
            double b1=B.x-A.x;
            double c1=A.x*B.y-B.x*A.y;
    
            double a2=C.y-D.y;
            double b2=D.x-C.x;
            double c2=C.x*D.y-D.x*C.y;
    
            ans.x=(b1*c2-b2*c1)/(a1*b2-a2*b1);
            ans.y=(a2*c1-a1*c2)/(a1*b2-a2*b1);
            return ans;
    }
    Point p_to_seg(Point p,Point a,Point b){        //点到线段的最近点
        Point tmp=p;
        tmp.x+=a.y-b.y;
        tmp.y+=b.x-a.x;
        if(cross(a-p,tmp-p)*cross(b-p,tmp-p)>0) return dist(p,a)<dist(p,b)?a:b;
        return line_inter(p,tmp,a,b);
    }
    void line_circle(Point c,double r,Point a,Point b,Point &p1,Point &p2){
        Point tmp=c;
        double t;
        tmp.x+=(a.y-b.y);//求垂直于ab的直线
        tmp.y+=(b.x-a.x);
        tmp=line_inter(tmp,c,a,b);
        t=sqrt(sqr(r)-sqr( dist(c,tmp)))/dist(a,b); //比例
        p1.x=tmp.x+(b.x-a.x)*t;
        p1.y=tmp.y+(b.y-a.y)*t;
        p2.x=tmp.x-(b.x-a.x)*t;
        p2.y=tmp.y-(b.y-a.y)*t;
    }
    struct Region {
        double st, ed;
        Region() {}
        Region(double st, double ed): st(st), ed(ed) {}
        bool operator < (const Region &rhs) const {
            if(sgn(st - rhs.st)) return st < rhs.st;
            return ed < rhs.ed;
        }
    };
    struct Circle {
        Point c;
        double r;
        vector<Region> reg;
        Circle() {}
        Circle(Point c, double r): c(c), r(r) {}
        void read() {
            c.read();
            scanf("%lf", &r);
        }
        void add(const Region &r) {
            reg.push_back(r);
        }
        bool contain(const Circle &cir) const {
            return sgn(dist(cir.c, c) + cir.r - r) <= 0;
        }
        bool intersect(const Circle &cir) const {
            return sgn(dist(cir.c, c) - cir.r - r) < 0;
        }
    };
    void intersection(const Circle &cir1, const Circle &cir2, Point &p1, Point &p2) {   //两圆相交 交点
        double l = dist(cir1.c, cir2.c);                            //两圆心的距离
        double d = (sqr(l) - sqr(cir2.r) + sqr(cir1.r)) / (2 * l);  //cir1圆心到交点直线的距离
        double d2 = sqrt(sqr(cir1.r) - sqr(d));                     //交点到 两圆心所在直线的距离
        Point mid = cir1.c + (cir2.c - cir1.c).unit() * d;
        Point v = rotate(cir2.c - cir1.c, PI / 2).unit() * d2;
        p1 = mid + v, p2 = mid - v;
    }
    Point calc(const Circle &cir, double angle) {
        Point p = Point(cir.c.x + cir.r, cir.c.y);
        return rotate(p, angle, cir.c);
    }
    const int MAXN = 1010;
    Circle cir[MAXN],cir2[MAXN];
    bool del[MAXN];
    int n;
    double get_area(Circle* cir,int n) {            //多个圆的相交面积
        double ans = 0;
        memset(del,0,sizeof(del));
        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) if(!del[j]) {                //删除被包含的圆
                if(i == j) continue;
                if(cir[j].contain(cir[i])) {
                    del[i] = true;
                    break;
                }
            }
        }
        for(int i = 0; i < n; ++i) if(!del[i]) {
            Circle &mc = cir[i];
            Point p1, p2;
            bool flag = false;
            for(int j = 0; j < n; ++j) if(!del[j]) {
                if(i == j) continue;
                if(!mc.intersect(cir[j])) continue;
                flag = true;
                intersection(mc, cir[j], p1, p2);                   //求出两圆的交点
                double rs = (p2 - mc.c).angle(), rt = (p1 - mc.c).angle();
                if(sgn(rs) < 0) rs += 2 * PI;
                if(sgn(rt) < 0) rt += 2 * PI;
                if(sgn(rs - rt) > 0) mc.add(Region(rs, PI * 2)), mc.add(Region(0, rt)); //添加相交区域
                else mc.add(Region(rs, rt));
            }
            if(!flag) {
                ans += PI * sqr(mc.r);
                continue;
            }
            sort(mc.reg.begin(), mc.reg.end());                 //对相交区域进行排序
            int cnt = 1;
            for(int j = 1; j < int(mc.reg.size()); ++j) {
                if(sgn(mc.reg[cnt - 1].ed - mc.reg[j].st) >= 0) {   //如果有区域可以合并,则合并
                    mc.reg[cnt - 1].ed = max(mc.reg[cnt - 1].ed, mc.reg[j].ed);
                } else mc.reg[cnt++] = mc.reg[j];
            }
            mc.add(Region());
            mc.reg[cnt] = mc.reg[0];
            for(int j = 0; j < cnt; ++j) {
                p1 = calc(mc, mc.reg[j].ed);
                p2 = calc(mc, mc.reg[j + 1].st);
                ans += cross(p1, p2) / 2;                           //
                double angle = mc.reg[j + 1].st - mc.reg[j].ed;
                if(sgn(angle) < 0) angle += 2 * PI;
                ans += 0.5 * sqr(mc.r) * (angle - sin(angle));      //弧所对应的的面积
            }
        }
        return ans;
    }
    double two_cir(Circle t1,Circle t2){            //两个圆的相交面积
        if(t1.contain(t2)||t2.contain(t1))    return PI * sqr(min(t2.r,t1.r));
        if(!t1.intersect(t2)) return 0;
        double ans=0,len=dist(t1.c,t2.c);
        double x=(sqr(t1.r)+sqr(len)-sqr(t2.r))/(2*len);
        double angle1=acos(x/t1.r),angle2=acos((len-x)/t2.r);
        ans=sqr(t1.r)*angle1+sqr(t2.r)*angle2-len*t1.r*sin(angle1);    // 两个扇形 减去一个四边形面积
        return ans;
    }
    double triangle_circle(Point a,Point b,Point o,double r){
        double sign=1.0;
        double ans=0;
        Point p1,p2;
        a=a-o;b=b-o;
        o=Point(0,0);
        if(sgn(cross(a,b))==0) return 0.0;
        if(sdist(a,o)>sdist(b,o)){
            swap(a,b);
            sign=-1.0;
        }
        if(sdist(a,o)<r*r+EPS){  //a 在内, b 在外
            if(sdist(b,o)<r*r+EPS) return cross(a,b)/2.0*sign;
            line_circle(o,r,a,b,p1,p2);
            if(dist(p1,b)>dist(p2,b)) swap(p1,p2);
            double ans1=fabs(cross(a,p1));
            double ans2=acos(p1*b/p1.length()/b.length())*r*r;
            ans=(ans1+ans2)/2.0;
            if(cross(a,b)<EPS&&sign>0.0||cross(a,b)>EPS&&sign<0.0) return -ans;
            return ans;
        }
        Point tmp=p_to_seg(o,a,b);
        if(sdist(o,tmp)>r*r-EPS){    //a,b所在直线与圆没有交点
            double angle=a*b/a.length()/b.length();
            if(angle>1.0) angle=1;
            if(angle<-1.0) angle=-1.0;
            ans=acos(a*b/a.length()/b.length())*r*r/2.0;
            if(cross(a,b)<EPS&&sign>0.0||cross(a,b)>EPS&&sign<0.0) return -ans;
            return ans;
        }
        line_circle(o,r,a,b,p1,p2);
        double cm=r/(dist(a,o)-r);
        Point m=Point((o.x+cm*a.x)/(1+cm),(o.y+cm*a.y)/(1+cm) );
        double cn=r/(dist(o,b)-r);
        Point n=Point( (o.x+cn*b.x)/(1+cn) , (o.y+cn*b.y)/(1+cn) );
        double angle= m*n/m.length()/n.length();
        if(angle>1.0) angle=1;
        if(angle<-1.0) angle=-1.0;
        double ans1 = acos(m*n/m.length()/n.length())*r*r;
        angle=p1*p2/p1.length()/p2.length() ;
        if(angle>1.0) angle=1;
        if(angle<-1.0) angle=-1.0;
        double ans2 = acos(p1*p2/p1.length()/p2.length() )*r*r-fabs(cross(p1,p2));
        ans=(ans1-ans2)/2.0;
        if(cross(a,b)<EPS&&sign>0.0||cross(a,b)>EPS&&sign<0.0) return -ans;
        return ans;
    }
    int main() {
        #ifndef ONLINE_JUDGE
        freopen("input.txt","r",stdin);
        #endif // ONLINE_JUDGE
        Point a,b,c;
        double x1,y1,h,x2,y2,r,t;
        while(scanf("%lf%lf%lf%lf%lf%lf",&x1,&y1,&h,&x2,&y2,&r)!=EOF){
            int n;cin>>n;
            Point pt[101010];
            for(int i=0;i<n;i++) pt[i].read();
            t=sqrt(2.0*h/10);
            c.x=x1;c.y=y1;
            c.x+=t*x2;
            c.y+=t*y2;
            pt[n]=pt[0];
            double ans=0;
            for(int i=0;i<n;i++) ans+=triangle_circle(pt[i],pt[i+1],c,r);
            printf("%.2f
    ",fabs(ans)+EPS);
        }
    }
  • 相关阅读:
    火狐浏览器清理缓存快捷键
    SVN使用教程总结
    如何登陆服务器
    get、put、post、delete含义与区别
    zookeeper 半数可用/选举机制
    zookeeper 分布式安装/配置/启动
    lucene 统计单词次数(词频tf)并进行排序
    selenium 爬取空间说说
    MapReduce自定义InputFormat,RecordReader
    reduce 阶段遍历对象添加到ArrayList中的问题
  • 原文地址:https://www.cnblogs.com/ainixu1314/p/4686877.html
Copyright © 2011-2022 走看看