[CERC2016]凸轮廓线

题意

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 }
View Code

 

转载于:https://www.cnblogs.com/GreenDuck/p/11409237.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值