zoukankan      html  css  js  c++  java
  • bzoj1043[HAOI2008]下落的圆盘 计算几何

    1043: [HAOI2008]下落的圆盘

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 1598  Solved: 676
    [Submit][Status][Discuss]

    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

    HINT

     

    Source

    可以考虑后放的盘子对先放的盘子造成的覆盖影响
    枚举每个盘,这个盘贡献的答案就是它的周长减去被后面的盘所覆盖的部分
    圆和圆相交部分长度可以转化成线段覆盖问题来计算:算出中轴线的角度x,再计算圆心到2交点的角度y,

    圆上被覆盖的弧度区间就是[x-y,x+y]
    几个圆与这个圆相交,把相交覆盖的弧转化成圆上的线段,做一个线段覆盖问题就可以解决

     1 #include<bits/stdc++.h>
     2 #define reg register
     3 #define N 1005
     4 using namespace std;
     5 int n,tp;double x[N],y[N],r[N],ans;const double pi=acos(-1);struct node{double l,r;}q[N<<1];
     6 double dis(int i,int j){return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));}
     7 bool con(int i,int j){return r[i]>=r[j]+dis(i,j);}
     8 bool cmp(node a,node b){return a.l<b.l;}
     9 void push(int i,int j){
    10     double d,k,t,mv;
    11     d=dis(i,j);k=atan2(y[j]-y[i],x[j]-x[i]);
    12     t=(d*d+r[i]*r[i]-r[j]*r[j])/2/d;
    13     mv=acos(t/r[i]);
    14     q[++tp]=(node){k-mv,k+mv};
    15 }
    16 double calc(int p){
    17     tp=0;
    18     for(reg int i=p+1;i<=n;i++)
    19     if(con(i,p))return 0;
    20     for(int i=p+1;i<=n;i++){
    21         if(con(p,i)||dis(i,p)>r[i]+r[p])continue;
    22         push(p,i);
    23     }
    24     for(reg int i=1;i<=tp;i++){
    25         if(q[i].l<0)q[i].l+=2*pi;
    26         if(q[i].r<0)q[i].r+=2*pi;
    27         if(q[i].l>q[i].r){
    28             q[++tp]=(node){0,q[i].r};
    29             q[i].r=2*pi;
    30         }
    31     }
    32     sort(q+1,q+1+tp,cmp);
    33     double cov=0,mx=q[1].l;
    34     for(reg int i=1;i<=tp;i++){
    35         mx=max(mx,q[i].l);
    36         if(q[i].r<=mx)continue;
    37         cov+=q[i].r-mx;mx=q[i].r;
    38     }
    39     double ret=r[p]*(2*pi-cov);
    40     return ret;
    41 }
    42 
    43 int main(){
    44     scanf("%d",&n);
    45     for(reg int i=1;i<=n;i++)
    46     scanf("%lf%lf%lf",&r[i],&x[i],&y[i]);
    47     for(reg int i=1;i<=n;i++)ans+=calc(i);
    48     printf("%.3lf
    ",ans);
    49     return 0;
    50 }
  • 相关阅读:
    mysql索引
    数据库修复
    数据库取值 三级分类后台遍历
    创建数据库!
    mysql按条件 导出sql
    nodejs 简单安装环境
    C++ 性能剖析 (一)
    C++ 性能剖析 (二):值语义 (value semantics)
    JavaScript Nested Function 的时空和身份属性
    C++ Reference 的“三位一体”诠释
  • 原文地址:https://www.cnblogs.com/wsy01/p/8178841.html
Copyright © 2011-2022 走看看