【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{BC} \cdot \vec{BC} \\
& = (\vec{AC}-\vec{AB}) \cdot (\vec{AC}-\vec{AB}) \\
& = | \vec{AC} |^2 + | \vec{AB} |^2 - 2|AC| |AB|cos A \\
\end{align}
$$
移项一下就是:
$$cos A=\frac{|AB|^2+|AC|^2-|BC|^2}{2|AB| |AC|}$$
一开始看了题解后想了一下就写了,求圆的交点..交点的极角...然后离散到的是$[0, \pi ]$的直线...然后喜闻乐见的悲剧了...
一定要知道!极角虽然是算出来了!但是同一个位置可能有两种角啊....为嘛我当时脑残...${\alpha + 2k \pi}$啊....
所以要区分一下..当极角<0时,先加上$2\pi$,然后如果原来极角小的比原来极角大的角要大了,说明它要分成两段来计算,即$[0, r]$, $[l, 2\pi ]$
然后将线段排序贪心取即可..(其实可以直接差分啊QAQ我是sb...
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <iostream>
#include <algorithm>
#include <queue>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i=0; i<(n); ++i)
#define for1(i,a,n) for(int i=(a);i<=(n);++i)
#define for2(i,a,n) for(int i=(a);i<(n);++i)
#define for3(i,a,n) for(int i=(a);i>=(n);--i)
#define for4(i,a,n) for(int i=(a);i>(n);--i)
#define CC(i,a) memset(i,a,sizeof(i))
#define read(a) a=getint()
#define print(a) printf("%d", a)
#define dbg(x) cout << (#x) << " = " << (x) << endl
#define error(x) (!(x)?puts("error"):0)
#define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; } const double PI=acos(-1), eps=1e-6;
int dcmp(double x) { return abs(x)<eps?0:(x<0?-1:1); }
struct ipt { double x, y; ipt(double _x=0, double _y=0) : x(_x), y(_y) {} };
struct icir { ipt x; double r; };
typedef ipt ivt;
ivt operator- (ipt &a, ipt &b) { return ivt(a.x-b.x, a.y-b.y); }
double iangle(ivt v) { return atan2(v.y, v.x); }
double sqr(double x) { return x*x; }
double dis(ipt &a, ipt &b) { return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); } bool getCC(icir &a, icir &b, double &ang1, double &ang2) {
static double d, ang;
d=dis(a.x, b.x);
if(dcmp(d)==0) return false;
if(dcmp(a.r+b.r-d)<=0) return false;
if(dcmp(a.r-b.r-d)>=0) return false;
ang=iangle(b.x-a.x);
double da=acos((sqr(d)+sqr(a.r)-sqr(b.r))/a.r/d/2);
ang1=ang-da; //dbg(da);
ang2=ang+da;
return true;
} const int N=1005;
int n;
icir a[N];
struct dat { double l, r; }line[N*2];
bool cmp(const dat &a, const dat &b) { return a.l==b.l?a.r>b.r:a.l<b.l; } double work(int now) {
int ln=0;
static double ang1, ang2;
for1(i, now+1, n) { double d=dis(a[now].x, a[i].x); if(dcmp(a[i].r-a[now].r-d)>=0) return 0; } //puts("here");
for1(i, now+1, n) {
if(getCC(a[now], a[i], ang1, ang2)==false) continue;
if(ang1<0) ang1+=PI*2;
if(ang2<0) ang2+=PI*2;
if(dcmp(ang1-ang2)>0) {
++ln; line[ln].l=0; line[ln].r=ang2;
++ln; line[ln].l=ang1; line[ln].r=PI*2;
}
else { ++ln; line[ln].l=ang1; line[ln].r=ang2; }
}
sort(line+1, line+1+ln, cmp);
double w=0, mx=0;
for1(i, 1, ln) {
if(dcmp(mx-line[i].r)>=0) continue;
mx=max(mx, line[i].l);
w+=line[i].r-mx;
mx=max(mx, line[i].r);
}
return a[now].r*(PI*2-w);
} int main() {
read(n);
for1(i, 1, n) scanf("%lf%lf%lf", &a[i].r, &a[i].x.x, &a[i].x.y);
double ans=0;
for1(i, 1, n) ans+=work(i);
printf("%.3f\n", ans);
return 0;
}
Description
有n个圆盘从天而降,后面落下的可以盖住前面的。求最后形成的封闭区域的周长。看下面这副图, 所有的红色线条的总长度即为所求. 
Input
n ri xi y1 ... rn xn yn
Output
最后的周长,保留三位小数
Sample Input
1 0 0
1 1 0
Sample Output
HINT
数据规模
n<=1000
Source
【BZOJ】1043: [HAOI2008]下落的圆盘(计算几何基础+贪心)的更多相关文章
- BZOJ 1043 HAOI2008 下落的圆盘 计算几何
题目大意:n个圆盘依次下落.求终于能看到的轮廓线面积 円盘反对! 让我们一起团结起来! 赶走円盘! 咳咳.非常神的一道题 今天去看了题解和白书才搞出来-- 首先我们倒着做 对于每一个圆盘处理出在它之后 ...
- BZOJ 1043 [HAOI2008]下落的圆盘 ——计算几何
倒着考虑,加入一个圆,判断和前面有没有完全覆盖的情况. 如果没有,和圆盘一一取交集,然后计算它们的并集,然后计算即可. #include <map> #include <cmath& ...
- bzoj 1043 [HAOI2008]下落的圆盘——圆的周长
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1043 算每个圆被它后面的圆盖住了多少圆弧即可.注意判断这个圆完全被后面盖住的情况. #inc ...
- 1043: [HAOI2008]下落的圆盘 - BZOJ
Description有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求.Input n ri xi y1 ... rn xn y ...
- 1043: [HAOI2008]下落的圆盘
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1725 Solved: 743[Submit][Status][Discuss] Descripti ...
- bzoj1043[HAOI2008]下落的圆盘 计算几何
1043: [HAOI2008]下落的圆盘 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1598 Solved: 676[Submit][Stat ...
- 【BZOJ1043】[HAOI2008]下落的圆盘 几何
[BZOJ1043][HAOI2008]下落的圆盘 Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红色线条的总长度即为所求. ...
- 题解:[HAOI2008]下落的圆盘
时空限制:1000ms / 128MB 原题链接: 洛谷 bzoj Description 有n个圆盘从天而降,后面落下的可以盖住前面的.求最后形成的封闭区域的周长.看下面这副图, 所有的红 色线条的 ...
- luogu P2510 [HAOI2008]下落的圆盘
LINK:下落的圆盘 计算几何.n个圆在平面上编号大的圆将编号小的圆覆盖求最后所有没有被覆盖的圆的边缘的总长度. 在做这道题之前有几个前置知识. 极坐标系:在平面内 由极点 极轴 和 极径组成的坐标系 ...
随机推荐
- 进入git diff 界面,无法继续输入命令
在终端,输入 git diff 文件名 命令之后回车,显示如下界面: 在网上查找,说输入q回车即可退出显示,执行,果然有效,输入h可以显示所有命令 命令如下: SUMMARY OF LESS COM ...
- MySQL入门书籍和方法分享
本文罗列了一些适用于MySQL及运维入门和进阶使用的书籍. 背景:各大论坛上总是有很多同学咨询想学习数据库,或者是为入行DBA做些准备.几年来作为一个MySQL DBA的成长过程有一些积累和感悟,特此 ...
- URAL 1654 Cipher Message 解题报告
题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1654 题意:简单的理解就是,把一个序列中相邻的且是偶数个相同的字符删除,奇数个的话就只保 ...
- PHP--TP框架----操作数据库
//操作数据库 //$attr = $m->select(); //查询所有数据 //$attr = $m->s ...
- 高阶函数复习:利用reduce和map把字符串转为数字
复习高阶函数的时候,有一道题想了半天解不出来.看了下别人的解法,发现学习编程,思维真的很重要. 习题: 利用map和reduce编写一个str2float函数,把字符串'123.456'转换成浮点数1 ...
- 谈JavaScript代码封装
前言 也算老生常谈的问题了,再深入搞一搞怎么玩儿封装,如果看到这篇文章的你,正好你也是追求完美的代码洁癖狂者,那么这篇文章相信非常适合你. 举一个例子,编写一个Person类,具有name和birth ...
- Fresco 源码分析(一) DraweeView-DraweeHierarchy-DraweeController(MVC) DraweeHierachy+DraweeController的分析
4.1.5.2 模型层DraweeHierachy继承体系以及各个类的作用 DraweeHierachy (I) --| SettableDraweeHierarchy (I) ------| Gen ...
- Redis经验谈
新浪作为全世界最大的Redis用户,在开发和运维方面有非常多的经验.本文作者来自新浪,希望能为业界提供一些亲身经历,让大家少走弯路. 使用初衷 从2010年上半年起,我们就开始尝试使用Redis,主要 ...
- 如何在ASP.NET 5和XUnit.NET中进行LocalDB集成测试
今天继续昨天的话题--单元测试,不过是在ASP.NET 5中的单元测试. 在当前的Visual Studio 2015 CTP6中,MSTest是不支持对ASP.NET 5项目进行单元测试的.因而,要 ...
- struts2文件下载及 <param name="inputName">inputStream</param>的理解
转自:http://blog.csdn.net/wnczwl369/article/details/7483290 转自:http://hi.baidu.com/c2_sun/item/934a542 ...