bzoj1043 下落的圆盘 计算几何

       (这几天好好学习计算几何(flag立起?))对于每一个i,求出这个圆盘会被后面的每一个圆盘覆盖哪一段。对于一个圆,可以用-pi到pi的弧度表示区间,然后就可以用线段覆盖的方法求出区间被覆盖了多少了。

       因此关键是对于两个圆盘i,j,如何求出i被覆盖的区间。首先对于两个圆的圆心x,y,可以求出向量(y-x)的atan2值,相当于与x轴正方向的夹角α,范围-pi到pi。然后根据余弦定理cos∠A=(b^2+c^2-a^2)/2bc,得到x的圆心到两圆的一个焦点的射线关于两圆连心线旋转角的余弦,然后用acos得到旋转角β,那么α±β就是对应的区间。注意边界问题,如果下界<-pi,就变成下界+2pi->pi,上界>pi同理。

       注意两圆不相交的情况。

AC代码如下(似乎并没有卡精度?):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define pi acos(-1.0)
#define N 2005
using namespace std;

int n,cnt;
struct point{ double x,y; }c[N];
struct circle{ point o; double r; }a[N];
double dist(point u,point v){
	return sqrt((u.x-v.x)*(u.x-v.x)+(u.y-v.y)*(u.y-v.y));
}
void add(double u,double v){ c[++cnt].x=u; c[cnt].y=v; }
void solve(circle u,circle v,double tmp){
	double t1=atan2(v.o.y-u.o.y,v.o.x-u.o.x),t2=acos((u.r*u.r+tmp*tmp-v.r*v.r)/(u.r*tmp*2));
	point q; q.x=t1-t2; q.y=t1+t2;
	if (q.x>=-pi && q.y<=pi) add(q.x,q.y); else
	if (q.x<-pi){ add(q.x+2*pi,pi); add(-pi,q.y); } else{
		add(q.x,pi); add(-pi,q.y-2*pi);
	}
}
bool cmp(point x,point y){ return x.x<y.x; }
double calc(){
	int i; double t=0,l=-10,r=-10; sort(c+1,c+cnt+1,cmp);
	for (i=1; i<=cnt; i++)
		if (c[i].x>r){
			t+=r-l; l=c[i].x; r=c[i].y;
		} else r=max(r,c[i].y);
	t+=r-l; return 2*pi-t;
}
int main(){
	scanf("%d",&n); int i,j; double ans=0;
	for (i=n; i; i--)
		scanf("%lf%lf%lf",&a[i].r,&a[i].o.x,&a[i].o.y);
	for (i=1; i<=n; i++){
		cnt=0;
		for (j=1; j<i; j++){
			double tmp=dist(a[i].o,a[j].o);
			if (a[j].r-a[i].r>tmp) break; 
			if (a[j].r+a[i].r>tmp && fabs(a[j].r-a[i].r)<tmp) solve(a[i],a[j],tmp);
		}
		if (j==i) ans+=a[i].r*calc();
	}
	printf("%.3f\n",ans);
	return 0;
}


by lych

2016.3.1

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值