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; }




  • 相关阅读:
    gitlab备份及迁移
    python paramiko 进行文件上传处理
    秒杀场景简介
    nmon--非常棒的LINUX/AIX性能计数器监测和分析工具
    使用wait()与notify()实现线程间协作
    【转】Spring bean处理——回调函数
    ldconfig和ldd用法
    tcpdump 获取http请求url
    clearfix清除浮动
    git push命令
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7055084.html
Copyright © 2011-2022 走看看