题意
https://www.luogu.org/problem/P3680
思考
拆点即可。
注意精度。
代码

1 // luogu-judger-enable-o2
2 #include<bits/stdc++.h>
3 using namespace std;
4 typedef long double ld;
5 const ld eps=1E-16;
6 const ld pi=acos(-1);
7 const ld inf=1E9;
8 inline bool equal(ld x,ld y)
9 {
10 return abs(x-y)<=eps;
11 }
12 struct pt
13 {
14 ld x,y;
15 pt(ld a=0,ld b=0){x=a,y=b;}
16 pt operator+(const pt&A){return pt(x+A.x,y+A.y);}
17 pt operator-(const pt&A){return pt(x-A.x,y-A.y);}
18 pt operator*(ld d){return pt(x*d,y*d);}
19 pt operator/(ld d){return pt(x/d,y/d);}
20 ld operator*(const pt&A){return x*A.y-y*A.x;}
21 void out(){cout<<"("<<x<<","<<y<<")";}
22 };
23 struct line
24 {
25 pt A,B;
26 line(pt a=pt(),pt b=pt())
27 {
28 A=a,B=b;
29 }
30 };
31 inline int cross(pt A,pt B)
32 {
33 ld d=A*B;
34 if(equal(d,0))
35 return 0;
36 return d>0?1:-1;
37 }
38 inline ld dis(pt A,pt B)
39 {
40 return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
41 }
42 inline pt intersection(line a,line b)
43 {
44 pt A=b.B-b.A,B=a.B-a.A,C=b.A-a.A;
45 if(cross(A,B)==0)
46 return pt(inf,inf);
47 ld d=-(B*C)/(B*A);
48 return b.A+A*d;
49 }
50 inline pt foot(pt A,line a)
51 {
52 return intersection(line(A,A+pt(a.B.y-a.A.y,a.A.x-a.B.x)),a);
53 }
54 inline bool seg(line a,line b)
55 {
56 return cross(a.A-b.A,b.B-b.A)*cross(a.B-b.A,b.B-b.A)==-1&&
57 cross(b.A-a.A,a.B-a.A)*cross(b.B-a.A,a.B-a.A)==-1;
58 }
59 pt O(0,0);
60 bool cmp(pt A,pt B)
61 {
62 ld x=atan2(A.y-O.y,A.x-O.x),y=atan2(B.y-O.y,B.x-O.x);
63 if(equal(x,y))
64 return dis(A,O)<dis(B,O);
65 return x<y;
66 }
67 vector<pt>convex(vector<pt>P)
68 {
69 int pos=0;
70 for(int i=1;i<P.size();++i)
71 if(P[i].x<P[pos].x)
72 pos=i;
73 swap(P[pos],P[0]);
74 O=P[0];
75 sort(P.begin()+1,P.end(),cmp);
76 vector<pt>ans;
77 int now=0;
78 for(int i=0;i<P.size();++i)
79 {
80 while(now>1&&cross(P[i]-ans[now-2],ans[now-1]-ans[now-2])!=-1)
81 ans.pop_back(),--now;
82 ans.push_back(P[i]);
83 ++now;
84 }
85 return ans;
86 }
87 inline bool cmpLine(line a,line b)
88 {
89 return atan2(a.A.y-a.B.y,a.A.x-a.B.x)<atan2(b.A.y-b.B.y,b.A.x-b.B.x);
90 }
91 inline bool onClockwise(line a,line b,line c)//b,c的交点在a顺时针方向
92 {
93 return cross(intersection(b,c)-a.A,a.B-a.A)==1;
94 }
95 inline bool isSame(line a,line b)
96 {
97 return cross(a.A-b.B,b.A-b.B)==0;
98 }
99 line wait[66666];
100 vector<line>halfPlane(vector<line>A)
101 {
102 vector<line>ans;
103 sort(A.begin(),A.end(),cmpLine);
104 int l=1,r=0;
105 for(int i=0;i<A.size();++i)
106 {
107 while(l<r&&!isSame(A[i],wait[r])&&onClockwise(A[i],wait[r-1],wait[r]))
108 --r;
109 while(l<r&&!isSame(A[i],wait[l])&&onClockwise(A[i],wait[l],wait[l+1]))
110 ++l;
111 if(!isSame(A[i],wait[r])||r==0)
112 wait[++r]=A[i];
113 else if(!onClockwise(wait[r],wait[r-1],A[i]))
114 wait[r]=A[i];
115 }
116 while(l<r&&onClockwise(wait[l],wait[r],wait[r-1]))
117 --r;
118 while(l<r&&onClockwise(wait[r],wait[l],wait[l+1]))
119 ++l;
120 for(int i=l;i<=r;++i)
121 ans.push_back(wait[i]);
122 return ans;
123 }
124 inline ld length(vector<pt>P)
125 {
126 ld sum=0;
127 for(int i=1;i<P.size();++i)
128 sum+=dis(P[i-1],P[i]);
129 sum+=dis(P[P.size()-1],P[0]);
130 return sum;
131 }
132 const ld base=10000;
133 int main()
134 {
135 ios::sync_with_stdio(false);
136 int n;
137 cin>>n;
138 vector<pt>P;
139 for(int i=1;i<=n;++i)
140 {
141 char ch;
142 cin>>ch;
143 ld x=i;
144 if(ch=='S')
145 {
146 P.push_back(pt(x,0));
147 P.push_back(pt(x+1,0));
148 P.push_back(pt(x+1,1));
149 P.push_back(pt(x,1));
150 }
151 else if(ch=='T')
152 {
153 P.push_back(pt(x,0));
154 P.push_back(pt(x+1,0));
155 P.push_back(pt(x+0.5,sqrt(3)/2));
156 }
157 else
158 {
159 for(ld j=0;j<base;j+=1)
160 {
161 ld ra=2*pi/base*j;
162 P.push_back(pt(x+0.5+cos(ra)/2,0.5+sin(ra)/2));
163 }
164 }
165 }
166 ld ans=length(convex(P));
167 cout<<fixed<<setprecision(7)<<ans<<endl;
168 return 0;
169 }
