LA 2572 Viva Confetti 离散化 *

56 篇文章 0 订阅
33 篇文章 0 订阅

题目地址:https://vjudge.net/problem/UVALive-2572

离散化:把每个圆看成是一段一段弧组成的

每个圆拿出来看一下,先求其上与其他所有圆的交点。每两个交点之间的那段弧要么可见要么不可见,在弧上任取一个点(这里取的的中点),将该点向内(圆心方向)和向外移动一个微小的eps距离,为p1,p2,看看p1和p2是否在最上层的圆内,如果在内部,那么该圆可见


#include <bits/stdc++.h>
using namespace std;
const int maxn=100+5;
const double PI=acos(-1);
const double EPS=1e-13;
#define REP(i,a,b)  for(int i=a;i<=(int)(b);++i)
#define REPD(i,a,b) for(int i=a;i>=(int)(b);--i)
int dcmp(double x){
	if(x>EPS) return 1;
	else if(x<-EPS) return -1;
	else return 0;
}
struct Point{
	double x,y;
	Point(double x=0,double y=0):x(x),y(y){}
};
typedef Point Vector;
Vector operator + (Vector A, Vector B) { return Vector(A.x+B.x, A.y+B.y); } 
Vector operator - (Vector A, Vector B) { return Vector(A.x-B.x, A.y-B.y); } 
Vector operator * (Vector A, double p) { return Vector(A.x*p, A.y*p); }
Vector operator / (Vector A, double p) { return Vector(A.x/p, A.y/p); }
double Angle(Vector v) { return atan2(v.y,v.x); }
double Length(Vector v) { return sqrt(v.x*v.x+v.y*v.y); }
double NormalizeAngle(double a){   //把(-180,180] 转化为 [0,360)
	return fmod(a+2*PI,2*PI);
}
void getCircleCircleIntersection(Point C1, double r1, Point C2, double r2,vector<double>& sol){
	double d = Length(C1-C2);
	if(dcmp(d)==0) return;
	if(dcmp(r1+r2-d)<0) return;
	if(dcmp(fabs(r1-r2)-d>0)) return; //内含,相离

	double ang=Angle(C2-C1);
	double dang=acos((r1*r1+d*d-r2*r2)/2/r1/d);
	sol.push_back(NormalizeAngle(ang+dang));
	if(dcmp(dang)!=0) sol.push_back(NormalizeAngle(ang-dang));
}

Point C[maxn*2];
double RC[maxn];
int n;
bool vis[maxn];
vector<double> rad;

inline Point point(Point p,double ang,double r){
	return Point(p.x+r*cos(ang),p.y+r*sin(ang));
}
void UpdateTop(Point p){
	REPD(i,n,1){
		double dist=Length(p-C[i]);
		if(dcmp(dist-RC[i])<0) { vis[i]=true; break; }
	}
}
int main(int argc, char const *argv[])
{
	// freopen("input.in","r",stdin);
	while(scanf("%d",&n)==1&&n){
		REP(i,1,n){
			double x,y,r;
			scanf("%lf%lf%lf",&x,&y,&r);
			C[i]=Point(x,y); RC[i]=r;
		}

		memset(vis,false,sizeof(vis));
		REP(i,1,n){
			rad.clear();
			rad.push_back(0);
			rad.push_back(2*PI);
			REP(j,1,n) {
				if(j==i) continue;
				getCircleCircleIntersection(C[i],RC[i],C[j],RC[j],rad);
			}
			sort(rad.begin(), rad.end());
			vector<double>::iterator it=unique(rad.begin(), rad.end());
			rad.erase(it,rad.end());

			REP(k,0,rad.size()-2){
				for(int side=-1;side<=1;side+=2){
					double nr=RC[i]+side*EPS*2;
					UpdateTop(point(C[i],(rad[k]+rad[k+1])/2,nr));
				}
			}
		}
		int cnt=0;
		REP(i,1,n) if(vis[i]) cnt++;
		printf("%d\n", cnt);
	}
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值