记录编号 120316 评测结果 AAAAAAA
题目名称 [POJ1688]海豚池 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.032 s
提交时间 2014-09-16 11:43:18 内存使用 0.33 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
#define sqr(x) ((x)*(x))
const int SIZE=1010;
const double eps=1e-18,jitter=1e-9,pi=acos(-1.0),INF=5000;
int N;
class CIRCLE{
public:
	double x,y,r;
	void print(void){
		cout<<"("<<x<<" "<<y<<")"<<" "<<r<<endl;
	}
}C[SIZE];
bool cut(CIRCLE c,double h,double &l,double &r){//切直线y=h
	if(fabs(c.y-h)>=c.r-eps) return false;
	double delta=sqrt(sqr(c.r)-sqr(c.y-h));
	l=c.x-delta,r=c.x+delta;
	return true;
}
bool qua_solve(double a,double b,double c,double &x1,double &x2){
	double delta=(b*b-4.0*a*c);
	if(delta<0) return false;
	x1=(-b+sqrt(delta))/(a*2.0),x2=(-b-sqrt(delta))/(a*2.0);
	return true;
}
bool cross(CIRCLE s,CIRCLE t,double &y1,double &y2){
	if(sqrt(sqr(s.x-t.x)+sqr(s.y-t.y))>s.r+t.r) return false;
	double a=2.0*(s.x-t.x),b=2.0*(s.y-t.y);
	double c=sqr(s.r)-sqr(t.r)-sqr(s.x)+sqr(t.x)-sqr(s.y)+sqr(t.y);
	if(fabs(a)<eps){
		y1=y2=-c/b;
		return true;
	}
	return qua_solve(sqr(b)/sqr(a)+1.0,2.0*b*c/sqr(a)+2.0*b*s.x/a-2.0*s.y,sqr(c)/sqr(a)+2.0*c*s.x/a+sqr(s.x)+sqr(s.y)-sqr(s.r),y1,y2);
}
class PR{
public:
	double l,r;
};
void print(PR a){
	cout<<"["<<a.l<<" "<<a.r<<"]";
}
bool operator < (PR a,PR b){
	if(a.r==b.r) return a.l<b.l;
	return a.r<b.r;
}
bool cross(PR a,PR b){
	if(b<a) swap(a,b);
	return b.l<a.r;
}
bool del[SIZE]={0};
PR s[SIZE];
void make_cut(PR out[SIZE],int &ot,double h){
	int tot=0;
	double l,r;
	for(int i=1;i<=N;i++)
		if(cut(C[i],h,l,r)) s[++tot]=(PR){l,r};
	sort(s+1,s+1+tot);
	memset(del,0,sizeof(del));
	for(int i=1;i<=tot;i++){
		for(int j=1;j<i;j++){
			if(del[j]) continue;
			if(s[i].l<s[j].r){
				s[i].l=min(s[i].l,s[j].l);
				del[j]=true;
			}
		}
	}
	int tt=0;
	for(int i=1;i<=tot;i++) if(!del[i]) s[++tt]=s[i];
	tot=tt;
	ot=0;
	s[0].r=-INF,s[tot+1].l=INF;
	for(int i=0;i<=tot;i++)
		if(s[i+1].l-s[i].r>eps) out[++ot]=(PR){s[i].r,s[i+1].l};
}
PR seg[2][SIZE];
int tot[2];
bool exi[SIZE];//在更上面一行有交叉的区间(即继承了它的区间)
int belong[2][SIZE];
vector<double> event;
vector<double> e;
int ans=0;
void addevt(double x){e.push_back(x);}
void make_event(void){
	for(int i=1;i<=N;i++) addevt(C[i].y-C[i].r),addevt(C[i].y+C[i].r);
	double h1,h2;
	for(int i=1;i<=N;i++)
		for(int j=i+1;j<=N;j++)
			if(cross(C[i],C[j],h1,h2))
				addevt(h1),addevt(h2);
	sort(e.begin(),e.end());
	for(int i=0;i<e.size();i++) if(!i||e[i]>e[i-1]+jitter*2.0) event.push_back(e[i]);
}
void scan(void){
	int bnum=1;
	tot[0]=1;
	belong[0][1]=1;
	for(int t=0;t<event.size();t++){
		memset(exi,0,sizeof(exi));
		memset(belong[1],0,sizeof(belong[1]));
		make_cut(seg[0],tot[0],event[t]-jitter);
		make_cut(seg[1],tot[1],event[t]+jitter);
		for(int i=1;i<=tot[0];i++){
			for(int j=1;j<=tot[1];j++){
				if(cross(seg[0][i],seg[1][j])){
					belong[1][j]=belong[0][i];
					exi[belong[0][i]]=true;
				}
			}
		}
		for(int i=1;i<=tot[0];i++){
			if(!exi[belong[0][i]]){
				ans++;
				exi[belong[0][i]]=true;
			}
		}
		for(int i=1;i<=tot[1];i++) if(!belong[1][i]) belong[1][i]=++bnum;
		memcpy(belong[0],belong[1],sizeof(belong[0]));
	}
}
void work(void){
	make_event();
	scan();
	printf("%d\n",ans);
}
void read(void){
	scanf("%d",&N);
	for(int i=1;i<=N;i++) scanf("%lf%lf%lf",&C[i].x,&C[i].y,&C[i].r);
}
int main(){
	freopen("dolphinpool.in","r",stdin);
	freopen("dolphinpool.out","w",stdout);
	read();
	work();
	return 0;
}