zoukankan      html  css  js  c++  java
  • uva 11978 Fukushima Nuclear Blast (二分+多边形与圆交)

    二分+多边形与圆交就可以了

      1 //#include<bits/stdc++.h>
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cmath>
      5 #include<cstring>
      6 #include<vector>
      7 #include<algorithm>
      8 using namespace std;
      9 typedef long long LL;
     10 
     11 const double PI = acos(-1.0);
     12 const double EPS = 1e-8;
     13 
     14 inline int sgn(double x) {
     15     return (x > EPS) - (x < -EPS);
     16 }
     17 
     18 struct Point {
     19     double x, y;
     20     Point() {}
     21     Point(double x, double y): x(x), y(y) {}
     22     void read() {
     23         scanf("%lf%lf", &x, &y);
     24     }
     25     double angle() {
     26         return atan2(y, x);
     27     }
     28     Point operator + (const Point &rhs) const {
     29         return Point(x + rhs.x, y + rhs.y);
     30     }
     31     Point operator - (const Point &rhs) const {
     32         return Point(x - rhs.x, y - rhs.y);
     33     }
     34     Point operator * (double t) const {
     35         return Point(x * t, y * t);
     36     }
     37     Point operator / (double t) const {
     38         return Point(x / t, y / t);
     39     }
     40     double operator *(const Point &b)const
     41     {
     42         return x*b.x + y*b.y;
     43     }
     44     double length() const {
     45         return sqrt(x * x + y * y);
     46     }
     47     Point unit() const {            //单位向量
     48         double l = length();
     49         return Point(x / l, y / l);
     50     }
     51 };
     52 double cross(const Point &a, const Point &b) {
     53     return a.x * b.y - a.y * b.x;
     54 }
     55 double sqr(double x) {
     56     return x * x;
     57 }
     58 double dist(const Point &p1, const Point &p2) {
     59     return (p1 - p2).length();
     60 }
     61 double sdist(Point a,Point b){
     62     return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
     63 }
     64 //向量 op 逆时针旋转 angle
     65 Point rotate(const Point &p, double angle, const Point &o = Point(0, 0)) {
     66     Point t = p - o;
     67     double x = t.x * cos(angle) - t.y * sin(angle);
     68     double y = t.y * cos(angle) + t.x * sin(angle);
     69     return Point(x, y) + o;
     70 }
     71 Point line_inter(Point A,Point B,Point C,Point D){ //直线相交交点
     72         Point ans;
     73         double a1=A.y-B.y;
     74         double b1=B.x-A.x;
     75         double c1=A.x*B.y-B.x*A.y;
     76 
     77         double a2=C.y-D.y;
     78         double b2=D.x-C.x;
     79         double c2=C.x*D.y-D.x*C.y;
     80 
     81         ans.x=(b1*c2-b2*c1)/(a1*b2-a2*b1);
     82         ans.y=(a2*c1-a1*c2)/(a1*b2-a2*b1);
     83         return ans;
     84 }
     85 Point p_to_seg(Point p,Point a,Point b){        //点到线段的最近点
     86     Point tmp=p;
     87     tmp.x+=a.y-b.y;
     88     tmp.y+=b.x-a.x;
     89     if(cross(a-p,tmp-p)*cross(b-p,tmp-p)>0) return dist(p,a)<dist(p,b)?a:b;
     90     return line_inter(p,tmp,a,b);
     91 }
     92 void line_circle(Point c,double r,Point a,Point b,Point &p1,Point &p2){
     93     Point tmp=c;
     94     double t;
     95     tmp.x+=(a.y-b.y);//求垂直于ab的直线
     96     tmp.y+=(b.x-a.x);
     97     tmp=line_inter(tmp,c,a,b);
     98     t=sqrt(sqr(r)-sqr( dist(c,tmp)))/dist(a,b); //比例
     99     p1.x=tmp.x+(b.x-a.x)*t;
    100     p1.y=tmp.y+(b.y-a.y)*t;
    101     p2.x=tmp.x-(b.x-a.x)*t;
    102     p2.y=tmp.y-(b.y-a.y)*t;
    103 }
    104 struct Region {
    105     double st, ed;
    106     Region() {}
    107     Region(double st, double ed): st(st), ed(ed) {}
    108     bool operator < (const Region &rhs) const {
    109         if(sgn(st - rhs.st)) return st < rhs.st;
    110         return ed < rhs.ed;
    111     }
    112 };
    113 struct Circle {
    114     Point c;
    115     double r;
    116     vector<Region> reg;
    117     Circle() {}
    118     Circle(Point c, double r): c(c), r(r) {}
    119     void read() {
    120         c.read();
    121         scanf("%lf", &r);
    122     }
    123     void add(const Region &r) {
    124         reg.push_back(r);
    125     }
    126     bool contain(const Circle &cir) const {
    127         return sgn(dist(cir.c, c) + cir.r - r) <= 0;
    128     }
    129     bool intersect(const Circle &cir) const {
    130         return sgn(dist(cir.c, c) - cir.r - r) < 0;
    131     }
    132 };
    133 void intersection(const Circle &cir1, const Circle &cir2, Point &p1, Point &p2) {   //两圆相交 交点
    134     double l = dist(cir1.c, cir2.c);                            //两圆心的距离
    135     double d = (sqr(l) - sqr(cir2.r) + sqr(cir1.r)) / (2 * l);  //cir1圆心到交点直线的距离
    136     double d2 = sqrt(sqr(cir1.r) - sqr(d));                     //交点到 两圆心所在直线的距离
    137     Point mid = cir1.c + (cir2.c - cir1.c).unit() * d;
    138     Point v = rotate(cir2.c - cir1.c, PI / 2).unit() * d2;
    139     p1 = mid + v, p2 = mid - v;
    140 }
    141 Point calc(const Circle &cir, double angle) {
    142     Point p = Point(cir.c.x + cir.r, cir.c.y);
    143     return rotate(p, angle, cir.c);
    144 }
    145 const int MAXN = 1010;
    146 Circle cir[MAXN],cir2[MAXN];
    147 bool del[MAXN];
    148 int n;
    149 double get_area(Circle* cir,int n) {            //多个圆的相交面积
    150     double ans = 0;
    151     memset(del,0,sizeof(del));
    152     for(int i = 0; i < n; ++i) {
    153         for(int j = 0; j < n; ++j) if(!del[j]) {                //删除被包含的圆
    154             if(i == j) continue;
    155             if(cir[j].contain(cir[i])) {
    156                 del[i] = true;
    157                 break;
    158             }
    159         }
    160     }
    161     for(int i = 0; i < n; ++i) if(!del[i]) {
    162         Circle &mc = cir[i];
    163         Point p1, p2;
    164         bool flag = false;
    165         for(int j = 0; j < n; ++j) if(!del[j]) {
    166             if(i == j) continue;
    167             if(!mc.intersect(cir[j])) continue;
    168             flag = true;
    169             intersection(mc, cir[j], p1, p2);                   //求出两圆的交点
    170             double rs = (p2 - mc.c).angle(), rt = (p1 - mc.c).angle();
    171             if(sgn(rs) < 0) rs += 2 * PI;
    172             if(sgn(rt) < 0) rt += 2 * PI;
    173             if(sgn(rs - rt) > 0) mc.add(Region(rs, PI * 2)), mc.add(Region(0, rt)); //添加相交区域
    174             else mc.add(Region(rs, rt));
    175         }
    176         if(!flag) {
    177             ans += PI * sqr(mc.r);
    178             continue;
    179         }
    180         sort(mc.reg.begin(), mc.reg.end());                 //对相交区域进行排序
    181         int cnt = 1;
    182         for(int j = 1; j < int(mc.reg.size()); ++j) {
    183             if(sgn(mc.reg[cnt - 1].ed - mc.reg[j].st) >= 0) {   //如果有区域可以合并,则合并
    184                 mc.reg[cnt - 1].ed = max(mc.reg[cnt - 1].ed, mc.reg[j].ed);
    185             } else mc.reg[cnt++] = mc.reg[j];
    186         }
    187         mc.add(Region());
    188         mc.reg[cnt] = mc.reg[0];
    189         for(int j = 0; j < cnt; ++j) {
    190             p1 = calc(mc, mc.reg[j].ed);
    191             p2 = calc(mc, mc.reg[j + 1].st);
    192             ans += cross(p1, p2) / 2;                           //
    193             double angle = mc.reg[j + 1].st - mc.reg[j].ed;
    194             if(sgn(angle) < 0) angle += 2 * PI;
    195             ans += 0.5 * sqr(mc.r) * (angle - sin(angle));      //弧所对应的的面积
    196         }
    197     }
    198     return ans;
    199 }
    200 double two_cir(Circle t1,Circle t2){            //两个圆的相交面积
    201     if(t1.contain(t2)||t2.contain(t1))    return PI * sqr(min(t2.r,t1.r));
    202     if(!t1.intersect(t2)) return 0;
    203     double ans=0,len=dist(t1.c,t2.c);
    204     double x=(sqr(t1.r)+sqr(len)-sqr(t2.r))/(2*len);
    205     double angle1=acos(x/t1.r),angle2=acos((len-x)/t2.r);
    206     ans=sqr(t1.r)*angle1+sqr(t2.r)*angle2-len*t1.r*sin(angle1);    // 两个扇形 减去一个四边形面积
    207     return ans;
    208 }
    209 double triangle_circle(Point a,Point b,Point o,double r){
    210     double sign=1.0;
    211     double ans=0;
    212     Point p1,p2;
    213     a=a-o;b=b-o;
    214     o=Point(0,0);
    215     if(sgn(cross(a,b))==0) return 0.0;
    216     if(sdist(a,o)>sdist(b,o)){
    217         swap(a,b);
    218         sign=-1.0;
    219     }
    220     if(sdist(a,o)<r*r+EPS){  //a 在内, b 在外
    221         if(sdist(b,o)<r*r+EPS) return cross(a,b)/2.0*sign;
    222         line_circle(o,r,a,b,p1,p2);
    223         if(dist(p1,b)>dist(p2,b)) swap(p1,p2);
    224         double ans1=fabs(cross(a,p1));
    225         double ans2=acos(p1*b/p1.length()/b.length())*r*r;
    226         ans=(ans1+ans2)/2.0;
    227         if(cross(a,b)<EPS&&sign>0.0||cross(a,b)>EPS&&sign<0.0) return -ans;
    228         return ans;
    229     }
    230     Point tmp=p_to_seg(o,a,b);
    231     if(sdist(o,tmp)>r*r-EPS){    //a,b所在直线与圆没有交点
    232         double angle=a*b/a.length()/b.length();
    233         if(angle>1.0) angle=1;
    234         if(angle<-1.0) angle=-1.0;
    235         ans=acos(a*b/a.length()/b.length())*r*r/2.0;
    236         if(cross(a,b)<EPS&&sign>0.0||cross(a,b)>EPS&&sign<0.0) return -ans;
    237         return ans;
    238     }
    239     line_circle(o,r,a,b,p1,p2);
    240     double cm=r/(dist(a,o)-r);
    241     Point m=Point((o.x+cm*a.x)/(1+cm),(o.y+cm*a.y)/(1+cm) );
    242     double cn=r/(dist(o,b)-r);
    243     Point n=Point( (o.x+cn*b.x)/(1+cn) , (o.y+cn*b.y)/(1+cn) );
    244     double angle= m*n/m.length()/n.length();
    245     if(angle>1.0) angle=1;
    246     if(angle<-1.0) angle=-1.0;
    247     double ans1 = acos(m*n/m.length()/n.length())*r*r;
    248     angle=p1*p2/p1.length()/p2.length() ;
    249     if(angle>1.0) angle=1;
    250     if(angle<-1.0) angle=-1.0;
    251     double ans2 = acos(p1*p2/p1.length()/p2.length() )*r*r-fabs(cross(p1,p2));
    252     ans=(ans1-ans2)/2.0;
    253     if(cross(a,b)<EPS&&sign>0.0||cross(a,b)>EPS&&sign<0.0) return -ans;
    254     return ans;
    255 }
    256 Point pt[5100];
    257 int main() {
    258     #ifndef ONLINE_JUDGE
    259     freopen("input.txt","r",stdin);
    260     #endif // ONLINE_JUDGE
    261     Point a,b,c;
    262     double x1,y1,h,x2,y2,r,p;
    263     int t,cas=0;cin>>t;
    264     while(t--){
    265         int n;cin>>n;
    266         for(int i=0;i<n;i++) pt[i].read();
    267         c.read();
    268         cin>>p;
    269         pt[n]=pt[0];
    270         double aLL=0,ans;
    271         for(int i=0;i<n;i++) aLL+=cross(pt[i],pt[i+1])/2.0;
    272         double l=0,r=1000000,mid;
    273         while(r-l>1e-3){
    274             mid=(l+r)/2;
    275             double sum=0;
    276             for(int i=0;i<n;i++) sum+=triangle_circle(pt[i],pt[i+1],c,mid);
    277             sum=fabs(sum);
    278             if(sum>=aLL*p/100) {
    279                 ans=mid;
    280                 r=mid;
    281             }
    282             else l=mid;
    283         }
    284         printf("Case %d: %.0f
    ",++cas,ans);
    285     }
    286 }
  • 相关阅读:
    G
    F
    E
    D
    机器学习第二次作业
    机器学习第一次作业
    机器学习作业一
    软工实践个人总结
    第11组 Beta版本演示
    第11组 Beta冲刺(5/5)
  • 原文地址:https://www.cnblogs.com/ainixu1314/p/4686966.html
Copyright © 2011-2022 走看看