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\n",ans);
    }
  return 0;
}
时间: 2024-10-15 10:28:57

ZOJ 1696 Viva Confetti 计算几何的相关文章

ZOJ 3720 Magnet Darts (计算几何,概率,判点是否在多边形内)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3720 题意: 在一个矩形区域投掷飞镖,因此飞镖只会落在整点上,投到每个点的得分是Ax+By.矩形区域里面有个多边形,如果飞镖投在多边形里面则得分,求最终的得分期望. 即:给定一个矩形内的所有整数点,判断这些点是否在一个多边形内 方法: 计算几何的判点是否在多边形内(几何模板),如果在,则令得分加(Ax+By)*以此点为中心边长为1的正方形面积 1 void solve()

uva 1308 - Viva Confetti(几何)

题目链接:uva 1308 - Viva Confetti 枚举一下两圆,处理出所有弧,然后判断每段弧的中点是否可见,可见的话该弧所在的圆也可见,以及该段弧下面的圆也可见. #include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <algorithm> using namespace std; const double pi = 4 * at

Viva Confetti(几何+圆盘覆盖问题)

Viva Confetti Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVALive 2572 Appoint description:  System Crawler  (2015-04-19) Description Do you know confetti? They are small discs of colored paper, and p

poj1418 Viva Confetti 判断圆是否可见

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Viva Confetti Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 881   Accepted: 361 Description Do you know confetti? They are small discs of colored paper, and people throw them a

zoj 2318 Get Out! 计算几何spfa判负环

题意:给出n个圆心及半径,再给出一个特殊圆心及半径,问这个圆能不能逃出这n个圆的包围 首先先处理一下,将所有圆平移,使特殊圆在原点上,然后其他圆半径加上特殊圆的半径,这样特殊圆就可看成一个点而已,问题变为该点是否可以逃出实际上对于相交的两个圆,我们可以用他们圆心连线来代替它们.这样问题变为是否存在一个多边形,使得原点在这个多边行内部. #include <stdio.h> #include <string.h> #include <algorithm> #include

UVaLive2572 poj1418 UVa1308 Viva Confetti

一次放下n个圆 问最终可见的圆的数量 应该是比较经典的问题吧 考虑一个圆与其他每个圆的交点O(n)个 将其割成了O(n)条弧 那么看每条弧的中点 分别向内向外调动eps这个点 则最上面的覆盖这个点的圆可见O(n) 总时间复杂度O(n ** 3) 怕炸精度,代码基本抄的rjl的 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include&

POJ 1696 Space Ant 计算几何 叉积的应用

题目大意:平面内有一些点,我们要通过一些方式来走遍这所有的点,要求一个点只能走一次,只能向左转而不能向右转.求遍历这些点的顺序. 思路:数据范围是可以怎么搞都0ms的(n<=50,case<=100),所以只要有思路就可以了. 只能左转,想想好像有点像凸包啊.但是这个题要遍历所有的点,所以就把已经走过的点删掉,然后像凸包一样的往前走,每次找一个没走过的极角最小的点走,然后把它标记上.最后都走完就全部遍历完了. CODE: #include <cmath> #include <

ZOJ 2675 Little Mammoth(计算几何)

求圆和矩形面积交 还是三角剖分去做即可 代码: #include<stdio.h> #include<string.h> #include<stdlib.h> #include<math.h> #include<algorithm> using namespace std; const double eps = 1e-8; const double pi = acos(-1.0); int dcmp(double x) { if(x > e

挑战程序设计竞赛 3.6 与平面和空间打交道的计算几何

POJ 1981:Circle and Points /* 题目大意:给出平面上一些点,问一个半径为1的圆最多可以覆盖几个点 题解:我们对于每个点画半径为1的圆,那么在两圆交弧上的点所画的圆,一定可以覆盖这两个点 我们对于每个点计算出其和其它点的交弧,对这些交弧计算起末位置对于圆心的极角, 对这些我们进行扫描线操作,统计最大交集数量就是答案. */ #include <cstdio> #include <algorithm> #include <cmath> #incl