裸题,直接上凸包,然后加上一个圆周即可
只是在这之前没写过旋转而已
1 const pi=3.14159265358979323; 2 eps=1e-8; 3 type point=record 4 x,y:double; 5 end; 6 7 var p:array[0..410010] of point; 8 q:array[0..410010] of longint; 9 n,i,k,t:longint; 10 ans,a,b,x,y,an,r:double; 11 12 procedure swap(var a,b:point); 13 var c:point; 14 begin 15 c:=a; 16 a:=b; 17 b:=c; 18 end; 19 20 function cmp(a,b:point):boolean; 21 begin 22 if abs(a.x-b.x)<eps then exit(a.y<b.y); 23 exit(a.x<b.x); 24 end; 25 26 procedure sort(l,r:longint); 27 var i,j:longint; 28 x:point; 29 begin 30 i:=l; 31 j:=r; 32 x:=p[(l+r) shr 1]; 33 repeat 34 while cmp(p[i],x) do inc(i); 35 while cmp(x,p[j]) do dec(j); 36 if not(i>j) then 37 begin 38 swap(p[i],p[j]); 39 inc(i); 40 dec(j); 41 end; 42 until i>j; 43 if l<j then sort(l,j); 44 if i<r then sort(i,r); 45 end; 46 47 function cross(i,j,k:longint):double; 48 begin 49 exit((p[i].x-p[k].x)*(p[j].y-p[k].y)-(p[j].x-p[k].x)*(p[i].y-p[k].y)); 50 end; 51 52 function dis(i,j:longint):double; 53 begin 54 exit(sqrt(sqr(p[i].x-p[j].x)+sqr(p[i].y-p[j].y))); 55 end; 56 57 function get(x,y,x0,y0:double):point; 58 begin 59 get.x:=cos(an)*x-sin(an)*y+x0; 60 get.y:=sin(an)*x+cos(an)*y+y0; 61 end; 62 63 begin 64 readln(n); 65 readln(b,a,r); 66 a:=a-2*r; 67 b:=b-2*r; 68 for i:=1 to n do 69 begin 70 readln(x,y,an); 71 inc(t); p[t]:=get(a/2,-b/2,x,y); 72 inc(t); p[t]:=get(a/2,b/2,x,y); 73 inc(t); p[t]:=get(-a/2,b/2,x,y); 74 inc(t); p[t]:=get(-a/2,-b/2,x,y); 75 end; 76 sort(1,t); 77 n:=t; 78 t:=1; 79 q[1]:=1; 80 for i:=2 to n do 81 begin 82 while (t>1) and (cross(i,q[t],q[t-1])>=-eps) do dec(t); 83 inc(t); 84 q[t]:=i; 85 end; 86 k:=t; 87 for i:=n-1 downto 1 do 88 begin 89 while (t>k) and (cross(i,q[t],q[t-1])>=-eps) do dec(t); 90 inc(t); 91 q[t]:=i; 92 end; 93 for i:=2 to t do 94 ans:=ans+dis(q[i],q[i-1]); 95 96 writeln(ans+2*r*pi:0:2); 97 end.