【BZOJ1043】[HAOI2008]下落的圆盘 几何

【BZOJ1043】[HAOI2008]下落的圆盘

Description

  有n个圆盘从天而降,后面落下的可以盖住前面的。求最后形成的封闭区域的周长。看下面这副图, 所有的红
色线条的总长度即为所求. 

Input

  第一行为1个整数n,N<=1000
接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标.

Output

  最后的周长,保留三位小数

Sample Input

2
1 0 0
1 1 0

Sample Output

10.472

题解:对于每个圆,我们枚举它后面的所有圆,先判断后面的圆是否完全覆盖了当前圆,再考虑相交的情况。我们求出后面的圆覆盖了当前圆的哪部分,然后我们将圆的周长拉直,那么每个被覆盖的部分都可以看成一个线段,求一下这些线段的并即可。

求圆交方法:直接用余弦定理求出覆盖角度的大小,然后用极角求出角的位置即可。如果角的大小>=2pi或<0,则需要特殊处理。

求线段并方法:我的方法可能有点naive,方法是将线段左端看成+1,右端看成-1,那么排个序求前缀和,前缀和>0的部分就是被覆盖的部分。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define pi acos(-1.0)
using namespace std;
struct circle
{
	double x,y,r;
	circle(){}
	circle(double a,double b)	{x=a,y=b;}
	circle operator + (circle a)	{return circle(x+a.x,y+a.y);}
	circle operator - (circle a)	{return circle(x-a.x,y-a.y);}
	circle operator * (double a)	{return circle(x*a,y*a);}
	circle operator / (double a)	{return circle(x/a,y/a);}
}c[1010];
struct node
{
	double x;
	int v;
}p[2010];
double ans;
double dist(circle a,circle b)	{return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
int n,tot,sum,flag;
bool cmp(node a,node b)
{
	return a.x<b.x;
}
int main()
{
	scanf("%d",&n);
	int i,j;
	for(i=1;i<=n;i++)	scanf("%lf%lf%lf",&c[i].r,&c[i].x,&c[i].y);
	for(i=1;i<=n;i++)
	{
		tot=sum=flag=0;
		for(j=i+1;j<=n;j++)
		{
			double dis=dist(c[i],c[j]);
			if(dis<=c[j].r-c[i].r)
			{
				flag=1;
				break;
			}
			if(dis>fabs(c[i].r-c[j].r)&&dis<=c[i].r+c[j].r)
			{
				double a=acos((c[i].r*c[i].r+dis*dis-c[j].r*c[j].r)/(2*c[i].r*dis));
				double b=atan2(c[j].y-c[i].y,c[j].x-c[i].x);
				p[++tot].x=b-a,p[tot].v=1,p[++tot].x=b+a,p[tot].v=-1;
				if(p[tot-1].x<0)	p[tot-1].x+=2*pi;
				if(p[tot].x<0)	p[tot].x+=2*pi;
				if(p[tot-1].x>=2*pi)	p[tot-1].x-=2*pi;
				if(p[tot].x>=2*pi)	p[tot].x-=2*pi;
				if(p[tot-1].x>p[tot].x)	sum++;
			}
		}
		if(flag)	continue;
		ans+=c[i].r*2*pi;
		if(!tot)	continue;
		sort(p+1,p+tot+1,cmp);
		for(j=1;j<=tot;j++)
		{
			if(sum)	ans-=c[i].r*(p[j].x-p[j-1].x);
			sum+=p[j].v;
		}
		if(sum)	ans-=c[i].r*(2*pi-p[tot].x);
	}
	printf("%.3lf",ans);
	return 0;
}
时间: 2024-10-13 15:19:10

【BZOJ1043】[HAOI2008]下落的圆盘 几何的相关文章

bzoj1043[HAOI2008]下落的圆盘 计算几何

1043: [HAOI2008]下落的圆盘 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1598  Solved: 676[Submit][Status][Discuss] Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求.  Input 第一行为1个整数n,N<=1000接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标

BZOJ1043 [HAOI2008]下落的圆盘

倒过来做,然后就变成了线段覆盖问题了. 线段覆盖就是贪心即可... 但是好烦好烦= =,需要耐心和几何基础2333 1 /************************************************************** 2 Problem: 1043 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:240 ms 7 Memory:872 kb 8 ****************************

【bzoj1043】[HAOI2008]下落的圆盘 计算几何

题目描述 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求. 输入 第一行为1个整数n,N<=1000接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标. 输出 最后的周长,保留三位小数 样例输入 2 1 0 0 1 1 0 样例输出 10.472 题解 计算几何 考虑从下到上的每一个圆,它被其它的圆覆盖了多少.即考虑它被覆盖了多少弧度. 考虑两个圆,如果相离则不覆盖,内含判断一下包含关系. 如果

BZOJ1043:[HAOI2008]下落的圆盘——题解

http://www.lydsy.com/JudgeOnline/problem.php?id=1043 Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红 色线条的总长度即为所求. Input 第一行为1个整数n,N<=1000 接下来n行每行3个实数,ri,xi,yi,表示下落时第i个圆盘的半径和圆心坐标. Output 最后的周长,保留三位小数 Sample Input 2 1 0 0 1 1 0 Sample Out

BZOJ 1043 HAOI2008 下落的圆盘 计算几何

题目大意:n个圆盘依次下落.求终于能看到的轮廓线面积 円盘反对! 让我们一起团结起来! 赶走円盘! 咳咳.非常神的一道题 今天去看了题解和白书才搞出来-- 首先我们倒着做 对于每一个圆盘处理出在它之后落下的圆盘和它的覆盖区间 然后求一个区间并就能算出这个圆盘的可见弧长 然后就是相交部分怎么求的问题了 首先两个圆必须相交 然后作圆心1到圆心2的向量 用atan2求出极角 然后利用余弦定理求出两个交点和圆心连线的夹角就可以 注意区间不在[0,2π]的部分要切割成还有一个区间 处理起来事实上不是非常麻

【BZOJ】1043: [HAOI2008]下落的圆盘(计算几何+贪心)

http://www.lydsy.com/JudgeOnline/problem.php?id=1043 唯一让我不会的就是怎么求圆的周长并QAAQ... 然后发现好神!我们可以将圆弧变成$[0, 2 \pi ]$的直线! 然后一定要注意!起点是$(1, 0)$(单位圆) 首先学了余弦定理... 在三角形ABC中 $$cos A=\frac{|AB|^2+|AC|^2-|BC|^2}{2|AB| |AC|}$$ 证明很简单... $$\begin{align}|{BC}|^2 & = \vec{

BZOJ 1043: [HAOI2008]下落的圆盘

Description 求几个圆交起来的周长..\(n\leqslant 10^3\) Solution 计算几何. 圆圆求交.. Code /************************************************************** Problem: 1043 User: BeiYu Language: C++ Result: Accepted Time:520 ms Memory:1308 kb *******************************

【bzoj_1043】[HAOI2008]下落的圆盘

水题?好像是的.(可惜我不会,默默捂脸= ̄ω ̄= 首先明确一点.两个圆相交,圆上的弧一定是从du-ang到du+ang的,不管是优弧还是劣弧.(du代表两圆心连线的atan2值,ang就是用余弦定理算出来的那个角) 然后就爽了. 把所有圆后面的圆扫一遍,看看有哪些焦点,用角度的形式记录下有哪些弧被覆盖,然后求并. 注意范围必须映射到一个长度为2π的区间内,否则求并的时候会出问题.

JZYZOJ1502 [haoi2008]下落的圆盘 计算几何 贪心

http://172.20.6.3/Problem_Show.asp?id=1502这种题用了快一天才写出来也是真的辣鸡.主要思路就是计算一下被挡住的弧度然后对弧度进行贪心.最开始比较困扰的是求弧度值及其起始位置的部分,弧度值很好求,位置有点恶心,我的起始位置设置的是圆的十二点方向顺时针到起始位置的弧度值,然后我分了四种情况讨论(因为遮挡的方向有两种不同情况,遮挡部分弧度值与180度的关系又是两种情况),应该是有更简单的方法的,但是我只能想出来这种了... 代码 1 #include<cstdi