POJ 1418 圆的基本操作以及 圆弧离散化

Viva Confetti

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 761   Accepted: 319

Description

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 decimal notation, with
up to 12 digits after the decimal point. The imprecision margin is +/- 5 x 10^(-13). That is, it is guaranteed that variations of less than +/- 5 x 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 0 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

给定一堆圆,求可见的圆有几个。

问别人的思路;


把圆弧离散化出来。

伏特跳蚤国王(497446970) 12:49:02

然后计算能看见的圆弧

Sd.无心插柳(450978053) 12:49:02

如果一个圆有条圆弧,没有被它之上的圆盖住,那肯定是可见的

Sd.无心插柳(450978053) 12:49:11

但还有一种可能

Sd.无心插柳(450978053) 12:49:35

Sd.无心插柳(450978053) 12:50:34

其实就是某条可见的圆弧盖住的圆

Sd.无心插柳(450978053) 12:50:38

也是可见的

rabbit(1337207267) 12:54:20

是不是一条可见的圆弧只能盖住一个圆。

Sd.无心插柳(450978053) 12:54:55

不是

Sd.无心插柳(450978053) 12:55:11

但可见的肯定是从上往下盖住的第一个圆

代码:

/* ***********************************************
Author :rabbit
Created Time :2014/7/8 13:49:36
File Name :3.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-14
#define pi acos(-1.0)
typedef long long ll;
int dcmp(double x){
	if(fabs(x)<eps)return 0;
	return x>0?1:-1;
}
struct Point{
	double x,y;
	Point(double _x=0,double _y=0){
		x=_x;y=_y;
	}
};
Point operator + (Point a,Point b){
	return Point(a.x+b.x,a.y+b.y);
}
Point operator - (Point a,Point b){
	return Point(a.x-b.x,a.y-b.y);
}
Point operator * (Point a,double p){
	return Point(a.x*p,a.y*p);
}
Point operator / (Point a,double p){
	return Point(a.x/p,a.y/p);
}
bool operator < (const Point &a,const Point &b){
	return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
bool operator == (const Point &a,const Point &b){
	return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0;
}
double Dot(Point a,Point b){
	return a.x*b.x+a.y*b.y;
}
double Length(Point a){
	return sqrt(Dot(a,a));
}
double Angle(Point a,Point b){
	return acos(Dot(a,b)/Length(a)/Length(b));
}
double angle(Point a){
	return atan2(a.y,a.x);
}
double Cross(Point a,Point b){
	return a.x*b.y-a.y*b.x;
}
Point vecunit(Point a){
	return a/Length(a);
}
Point Normal(Point a){
	return Point(-a.y,a.x)/Length(a);
}
Point Rotate(Point a,double rad){
	return Point(a.x*cos(rad)-a.y*sin(rad),a.x*sin(rad)+a.y*cos(rad));
}
Point GetLineIntersection(Point p,Point v,Point q,Point w){
	Point u=p-q;
	double t=Cross(w,u)/Cross(v,w);
	return p+v*t;
}
struct Line{
	Point p,v;
	double ang;
	Line(){}
	Line(Point _p,Point _v):p(_p),v(_v){
		ang=atan2(v.y,v.x);
	}
	Point point(double a){
		return p+(v*a);
	}
	bool operator < (const Line &L) const{
		return ang<L.ang;
	}
};
Point GetLineIntersection(Line a,Line b){
	return GetLineIntersection(a.p,a.v,b.p,b.v);
}
struct Circle{
	Point c;
	double r;
	Circle(){}
	Circle(Point _c,double _r):c(_c),r(_r){}
	Point point(double a){
		return Point(c.x+cos(a)*r,c.y+sin(a)*r);
	}
};
Circle C[200];
bool vis[200];
vector<double> pp[200];
int GetCircleCircleIntersection(int s1,int s2){
	Circle c1=C[s1],c2=C[s2];
	double d=Length(c1.c-c2.c);
	if(dcmp(d)==0){
		if(dcmp(c1.r-c2.r)==0)return -1;
		return 0;
	}
	if(dcmp(c1.r+c2.r-d)<0)return 0;
	if(dcmp(fabs(c1.r-c2.r)-d)>0)return 0;
	double a=angle(c2.c-c1.c);
	double da=acos((c1.r*c1.r+d*d-c2.r*c2.r)/(2*c1.r*d));
	Point p1=c1.point(a-da),p2=c1.point(a+da);
	if(p1==p2)return 1;
	pp[s1].push_back(a+da);
	pp[s1].push_back(a-da);
	return 2;
}
bool PointInCircle(Point p, Circle C){
    double dist = Length(p - C.c);
    if(dcmp(dist - C.r) > 0) return 0;
    else return 1;
}
bool CircleInCircle(Circle A, Circle B){
    double cdist = Length(A.c - B.c);
    double rdiff = B.r - A.r;
    if(dcmp(A.r - B.r) <= 0 && dcmp(cdist - rdiff) <= 0) return 1;
    return 0;
}
int main()
{
     //freopen("data.in","r",stdin);
     //freopen("data.out","w",stdout);
     int n;
	 while(~scanf("%d",&n)&&n){
		 memset(vis,0,sizeof(vis));
		 for(int i=0;i<n;i++)pp[i].clear();
		 for(int i=0;i<n;i++)
			 scanf("%lf%lf%lf",&C[i].c.x,&C[i].c.y,&C[i].r);
		 for(int i=0;i<n;i++)
			 for(int j=0;j<n;j++){
				 if(i==j)continue;
				 GetCircleCircleIntersection(i,j);
			 }
		 for(int i=0;i<n;i++){
			 sort(pp[i].begin(),pp[i].end());
			 pp[i].resize(unique(pp[i].begin(),pp[i].end())-pp[i].begin());
		 }
		 for(int i=0;i<n;i++){
			 if(pp[i].size()==0){
				 bool ok=1;
				 for(int j=i+1;j<n;j++)
					 if(CircleInCircle(C[i],C[j])){
						 ok=0;break;
					 }
				 if(ok)vis[i]=1;
			//	 cout<<"han->1"<<endl;
			 }
			 else{
			//	 cout<<"han->2"<<endl;
				 int sz=pp[i].size();
				 pp[i].push_back(pp[i][0]);
				 for(int j=0;j<sz;j++){
					 Point dd=C[i].point((pp[i][j]+pp[i][j+1])/2);
					 bool ok=1;
					 for(int k=i+1;k<n;k++)
						 if(PointInCircle(dd,C[k])){
						//	 cout<<dd.x<<" "<<dd.y<<" "<<k<<endl;
							 ok=0;break;
						 }
					 if(ok){
						 vis[i]=1;
						 for(int k=i-1;k>=0;k--)
							 if(PointInCircle(dd,C[k])){
								 vis[k]=1;break;
							 }
					 }
				 }
			 }
		 }
		 int ans=0;
	//	 cout<<"han  ";for(int i=0;i<n;i++)cout<<vis[i]<<" ";cout<<endl;
		 for(int i=0;i<n;i++)
			 if(vis[i])ans++;
		 cout<<ans<<endl;
	 }
     return 0;
}

POJ 1418 圆的基本操作以及 圆弧离散化,布布扣,bubuko.com

时间: 2024-10-16 17:52:03

POJ 1418 圆的基本操作以及 圆弧离散化的相关文章

Poj 2528 Mayor&#39;s posters (线段树+离散化)

题目连接: http://poj.org/problem?id=2528 题目大意: 有10000000块瓷砖,n张海报需要贴在墙上,每张海报所占的宽度和瓷砖宽度一样,长度是瓷砖长度的整数倍,问按照所给海报顺序向瓷砖上贴海报,最后有几张海报是可见的? 解题思路: 因为瓷砖块数和海报张数多,首选线段树,如果按照常规的建树方式,把瓷砖当做数的节点,肯定会MTL......... 所以我们可以用海报的起点和终点当做树的节点,这样树的节点才有20000个,但是这样建树的话,求海报覆盖了那些节点会很复杂,

POJ 3277 City Horizon(线段树+扫描线+离散化)

题目地址:POJ 3277 水题..稍微处理一下然后用求面积并的方法求即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的 要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算 不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码 我

poj 1733 Parity game 并查集 离散化

点击打开链接题目链接 Parity game Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6249   Accepted: 2413 Description Now and then you play the following game with your friend. Your friend writes down a sequence consisting of zeroes and ones. You cho

POJ 1185 炮兵阵地 状压DP+离散化优化

一开始能想到的状态就只有位压两行和当前行的行号,这样无论是空间和时间都是无法接受的. 但是因为炮兵的攻击范围比较大,而且又有地形限制,每一行的状态其实不多了,打表看了一下不超过80种,离散化一下就可以随意DP了. 据说题目也可以抽象成二分图最大匹配来搞?感觉复杂度有点高 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #i

POJ - 3666 Making the Grade(dp+离散化)

Description A straight dirt road connects two fields on FJ's farm, but it changes elevation more than FJ would like. His cows do not mind climbing up or down a single slope, but they are not fond of an alternating succession of hills and valleys. FJ

poj 3581 Sequence(后缀数组,离散化)详解

题目链接:http://poj.org/problem?id=3581 题目大意:给一个数列,要求将其分成三段,每段进行翻转后形成后合并成新数列,求按字典顺序最小的新数列. 思路: 注意到题目中数列a0,a2,a3...an-1, a0是最大的,因此将原数列翻转后an-1,an-2,...,a1,a0,求后缀数组, sa[0]所代表的后缀即为所求第一段翻转后的数列,注意到要分成三份,因此sa[0]<2时不可取,此时找sa[1], sa[2]看是否可取.找第一个位置后,设剩下 数列是an-1,an

POJ 2299 Ultra-QuickSort(树状数组+离散化)

http://poj.org/problem?id=2299 题意:给出一组数,求逆序对. 思路: 这道题可以用树状数组解决,但是在此之前,需要对数据进行一下预处理. 这道题目的数据可以大到999,999,999,但数组肯定是无法开这么大的,但是每组数据最多只有500000个,那么,怎么办呢,离散化! 离散化,也就是将数据和1~n做一一映射. 比如: 9 1 0 5 4 离散化之后变成 5 2 1 4 3 这样的话,就可以放心的开数组啦! 至于树状数组的计算过程,我懒得写了,直接摘抄一下大神的h

poj 2299 Ultra-QuickSort(归并排序或是bit 树+离散化皆可)

题意:给一个数组,计算需要的冒泡排序的次数,元素个数很大,不能用n^2的冒泡排序计算. 解析:这题实际上就是求逆序对的个数,可以用归并排序的方法,我这里用另一种方法写,bit树+离散化.由于元素的值可以达到很大,但元素个数最多只有500000个,可以先对这些数排序,离散化一下,比如5个数:1 5 8  233333333 122222,排序后他们对应的标号可以是1 2 3 5 4:每次插入一个数时add(val,1),计算该数以及之前所有的数的个数sum(val);那么逆序对的个数=当前这个数的