1043: [HAOI2008]下落的圆盘 - BZOJ

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

n ri xi y1 ... rn xn yn
Output

最后的周长,保留三位小数
Sample Input
2
1 0 0
1 1 0
Sample Output
10.472

数据规模
n<=1000

 

 

调了一晚上外加下午(弱菜写计算几何,tan函数都抄错了)

对每一个圆计算覆盖区间,然后排序,再区间合并,注意范围,我是全部弄到0到2π里

再膜拜一下z55250825,最后还是他看出错误来的

 

  1 uses math;

  2 const

  3     maxn=1010;

  4     eps=1e-7;

  5 var

  6     r,x,y,ll,rr:array[0..maxn*2]of double;

  7     n,tot:longint;

  8     ans:double;

  9 

 10 procedure init;

 11 var

 12     i:longint;

 13 begin

 14     read(n);

 15     for i:=1 to n do

 16       read(r[i],x[i],y[i]);

 17 end;

 18 

 19 function angle(a,b,c:double):double;

 20 begin

 21     exit(arccos((a*a+b*b-c*c)/(2*a*b)));

 22 end;

 23 

 24 function tan(x,y:double):double;

 25 var

 26     a:double;

 27 begin

 28     if abs(x)<eps then

 29     begin

 30       if y>-eps then exit(pi/2)

 31       else exit(pi*3/2);

 32     end;

 33     if abs(y)<eps then

 34     begin

 35       if x>-eps then exit(0)

 36       else exit(pi);

 37     end;

 38     a:=arctan(y/x);

 39     if a<-eps then a:=-a;

 40     if x>-eps then

 41       if y>-eps then exit(a)

 42       else exit(2*pi-a)

 43     else

 44       if y>-eps then exit(pi-a)

 45       else exit(pi+a);

 46 end;

 47 

 48 procedure swap(var x,y:double);

 49 var

 50     t:double;

 51 begin

 52     t:=x;x:=y;y:=t;

 53 end;

 54 

 55 procedure sort(l,r:longint);

 56 var

 57     i,j:longint;

 58     y:double;

 59 begin

 60     i:=l;

 61     j:=r;

 62     y:=ll[(l+r)>>1];

 63     repeat

 64       while ll[i]+eps<y do

 65         inc(i);

 66       while ll[j]>y+eps do

 67         dec(j);

 68       if i<=j then

 69       begin

 70         swap(ll[i],ll[j]);

 71         swap(rr[i],rr[j]);

 72         inc(i);

 73         dec(j);

 74       end;

 75     until i>j;

 76     if i<r then sort(i,r);

 77     if l<j then sort(l,j);

 78 end;

 79 

 80 procedure work;

 81 var

 82     i,j:longint;

 83     d,a,b,sum,xx,yy:double;

 84     cover:boolean;

 85 begin

 86     for i:=1 to n do

 87       begin

 88         tot:=0;

 89         cover:=false;

 90         for j:=i+1 to n do

 91           begin

 92             d:=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));

 93             if (r[i]+r[j]-d<eps)or(d+r[j]-r[i]<eps) then continue;

 94             if d+r[i]-r[j]<eps then

 95             begin

 96               cover:=true;

 97               break;

 98             end;

 99             a:=tan(x[j]-x[i],y[j]-y[i]);

100             b:=angle(d,r[i],r[j]);

101             inc(tot);

102             ll[tot]:=a-b;

103             rr[tot]:=a+b;

104             if ll[tot]<-eps then

105             begin

106               ll[tot+1]:=2*pi+ll[tot];

107               rr[tot+1]:=2*pi;

108               ll[tot]:=0;

109               inc(tot);

110             end;

111             if rr[tot]>2*pi+eps then

112             begin

113               rr[tot+1]:=rr[tot]-2*pi;

114               ll[tot+1]:=0;

115               rr[tot]:=2*pi;

116               inc(tot);

117             end;

118           end;

119         if cover then continue;

120         sort(1,tot);

121         inc(tot);

122         ll[tot]:=100;

123         rr[tot]:=100;

124         sum:=0;

125         xx:=0;

126         yy:=0;

127         for j:=1 to tot do

128           if ll[j]+eps<=yy then

129           begin

130             if rr[j]+eps<=yy then continue;

131             yy:=rr[j];

132           end

133           else

134           begin

135             sum:=sum+yy-xx;

136             xx:=ll[j];

137             yy:=rr[j];

138           end;

139         ans:=ans+(2*pi-sum)*r[i];

140       end;

141     write(ans:0:3);

142 end;

143 

144 begin

145     init;

146     work;

147 end.
View Code

 

你可能感兴趣的:(2008)