zoukankan      html  css  js  c++  java
  • ZOJ 1696 Viva Confetti 计算几何


    计算几何:按顺序给n个圆覆盖。问最后能够有几个圆被看见。。

    对每一个圆求和其它圆的交点,每两个交点之间就是可能被看到的圆弧,取圆弧的中点,往外扩展一点或者往里缩一点,从上往下推断有没有圆能够盖住这个点,能盖住这个点的最上面的圆一定是可见的


    Viva Confetti

    Time Limit: 2 Seconds      Memory Limit: 65536 KB

    Do you know confetti?

    They are small discs of colored paper, and people throw them around during parties or festivals. Since people throw lots of confetti, they may end up stacked one on another, so there may be hidden ones underneath.

    A handful of various sized confetti have been dropped on a table. Given their positions and sizes, can you tell us how many of them you can see?

    The following figure represents the disc configuration for the first sample input, where the bottom disc is still visible.


    Input

    The input is composed of a number of configurations of the following form.

    n
    x1 y1 r1
    x2 y2 r2
    . . .
    xn yn rn

    The first line in a configuration is the number of discs in the configuration (a positive integer not more than 100), followed by one line descriptions of each disc: coordinates of its center and radius, expressed as real numbers in the decimal notation, with up to 12 digits after the decimal point. The imprecision margin is 5*10^-13. That is, it is guaranteed that variations of less than 5*10^-13 on input values do not change which discs are visible. Coordinates of all points contained in discs are between -10 and 10.

    Confetti are listed in their stacking order, x1 y1 r1 being the bottom one and xn yn rn the top one. You are observing from the top.

    The end of the input is marked by a zero on a single line.


    Output

    For each configuration you should output the number of visible confetti on a single line.


    Sample Input

    3
    0 0 0.5
    -0.9 0 1.00000000001
    0.9 9 1.00000000001
    5
    0 1 0.5
    1 1 1.00000000001
    0 2 1.00000000001
    -1 1 1.00000000001
    0 -0.00001 1.00000000001
    5
    0 1 0.5
    1 1 1.00000000001
    0 2 1.00000000001
    -1 1 1.00000000001
    0 0 1.00000000001
    2
    0 0 1.0000001
    0 0 1
    2
    0 0 1
    0.00000001 0 1
    0


    Sample Output

    3
    5
    4
    2
    2


    Source: Asia 2002, Kanazawa (Japan)
    Submit    Status


    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    
    const double eps=5*(1e-13);
    const double pi=acos(-1.0);
    
    int n;
    
    struct Point
    {
      double x,y;
      Point(){}
      Point(double _x,double _y):x(_x),y(_y){}
    };
    
    struct Circle
    {
      Point c;
      double r;
      Circle(){}
      Circle(Point _c,double _r):c(_c),r(_r){}
      Point point(double x) {return Point(c.x+cos(x)*r,c.y+sin(x)*r);}
    };
    
    double normal(double x)
    {
      return x-floor(x/(2*pi))*2*pi;
    }
    
    double dcmp(double x)
    {
      if(fabs(x)<=eps) return 0;
      return (x<0)?

    -1:1; } double DIST(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } Circle C[200]; double a[1000]; int tot=0; bool flag[110]; void check(Point x) { for(int i=n-1;i>=0;i--) { double d=DIST(x,C[i].c); if(dcmp(d-C[i].r)<0) { flag[i]=true; break; } } } int main() { while(scanf("%d",&n)!=EOF&&n) { memset(flag,0,sizeof(flag)); for(int i=0;i<n;i++) { double x,y,z; scanf("%lf%lf%lf",&x,&y,&z); C[i]=Circle(Point(x,y),z); } for(int i=0;i<n;i++) { tot=0; for(int j=0;j<n;j++) { if(i==j) continue; double dist=DIST(C[i].c,C[j].c); double ri=C[i].r,rj=C[j].r; if(dcmp(dist-ri-rj)>=0||dcmp(dist-fabs(ri-rj))<=0) continue; double t=atan2(C[j].c.y-C[i].c.y,C[j].c.x-C[i].c.x); double dt= acos((ri*ri+dist*dist-rj*rj)/(2.*ri*dist)); a[tot++]=normal(t+dt); a[tot++]=normal(t-dt); } a[tot++]=0;a[tot++]=2*pi; sort(a,a+tot); tot=unique(a,a+tot)-a; for(int j=0;j<tot-1;j++) { double u=(a[j]+a[j+1])/2; double r1=C[i].r+eps,r2=C[i].r-eps; Point p1=Point(C[i].c.x+r1*cos(u),C[i].c.y+r1*sin(u)); Point p2=Point(C[i].c.x+r2*cos(u),C[i].c.y+r2*sin(u)); check(p1); check(p2); } } int ans=0; for(int i=0;i<n;i++) if(flag[i]) ans++; printf("%d ",ans); } return 0; }




  • 相关阅读:
    javascript简易下拉菜单效果
    精通javascript笔记(智能社)——简易tab选项卡及应用面向对象方法实现
    精通JS正则表达式(转)
    精通javascript笔记(智能社)——数字时钟
    ERROR: transport error 202: bind failed: Address already in use
    理解git对象
    InvocationHandler中invoke()方法的调用问题
    深入理解Java Proxy机制(转)
    IP、子网的详述 ——IP分类、网关地址,子网掩码、子网作用(转)
    getRequestDispatcher()与sendRedirect()的区别
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7055084.html
Copyright © 2011-2022 走看看