An overnight dance in discotheque题解

An overnight dance in discotheque题解

其实可以看做一道结论题:只将覆盖次数为2的圆放到另一组。

我们可以将结论分解为两部分:

1.将覆盖次数为2的圆放到另一组。

2.不将覆盖次数大于2的圆放到另一组

1
2

在图中我们可以看到,覆盖次数为2的圆c3被放到另一空间,

此操作增加的面积为2(S圆c3-(S圆c4+S圆c5)[即S阴影<原来的>])=2S空<原来的>

覆盖次数为2的圆,S圆肯定大于等于S阴影<原来的>,S空<原来的>一定大于等于0,

就算里面的圆也有一些放放到另一组,S圆也一定定大于等于S阴影,故一定放。

将覆盖次数为2的圆放到另外一空间后,

原来覆盖次数大于2的圆,我们对任意互相包含的一组进行讨论。

若每组最外围的圆原先覆盖次数为奇数,即为阴影,则

放到另一空间,阴影变成空,空变成阴影,变化后的S阴影仍然小与S在外围的圆=S阴+S空(现在的)
减小的量为S空(现在的),S阴之前的。

而原先被这一组包括,却没有放到另一空间的,

若最外围为阴影,不变。

否则,增量<=S最外围的圆<=S阴(放到另一空间的之前的)(即减少量),故不放。

若每组最外围的圆原先覆盖次数为偶数,即为空,

现在的空就是之前的空,不变,则第一空间的增量<=S最外围的圆,另一空间的减少量等于S最外围的圆,故也不放。
得证

没有画图工具,口胡说得很绕,敬请理解。

大家还是感性理解一下算了。

贴一下代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1006;
int n,cnt=0,f[N],rr[N],head[N];
struct edge{int nxt,to;}e[N];
struct circle{long long x,y,r;}o[N];
double ans=0.00,pai=3.1415926535898;
inline void add(int u,int v){e[++cnt].nxt=head[u],e[cnt].to=v,head[u]=cnt;}
inline int read(){
   int T=0,F=1; char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();}
   while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar();
   return F*T;
}
bool check(int u,int v){
     double t=sqrt((o[u].x-o[v].x)*(o[u].x-o[v].x)+(o[u].y-o[v].y)*(o[u].y-o[v].y));
     return (1.0000*o[v].r>=t+o[u].r);
}
void dfs(int u,int d,long long v){
     if(d==2) v*=-1;
     ans+=v*pai*o[u].r*o[u].r;
     for(int i=head[u];i;i=e[i].nxt) dfs(e[i].to,d+1,-v); 
}
bool cmp(circle u,circle v){return u.r>v.r;}
int main(){
    n=read();
    for(int i=1;i<=n;++i) f[i]=n+1,rr[i]=1e7,o[i].x=read(),o[i].y=read(),o[i].r=read();
    sort(o+1,o+n+1,cmp);
    for(int i=1;i<=n;++i)
        for(int j=1;j<i;++j)
            if(check(i,j)&&o[j].r<rr[i]) f[i]=j,rr[i]=o[j].r;
    for(int i=1;i<=n;++i) add(f[i],i);
    dfs(n+1,0,-1),printf("%.9lf",ans);
    return 0;
} 
posted @ 2019-08-07 21:44  lsoi_ljk123  阅读(149)  评论(0编辑  收藏  举报