题目大意 : 一行紧挨的图形 (仅有正方形,圆形,等边三角形)求构成图形的凸包
最多只有二十个图形
一眼过去,正方形,三角形这不就是可以直接求距离吗,加上对圆形的一些切线等等
处理,不就可以乱搞过去了吗,但是
“ 瞎搞有难度,乱搞需谨慎 ”
思路:既然是一道大水题,我们自然有更加偏模板的的方式去完成
考虑凸包,如果没有圆形,仅仅三角形和正方形的话,自然只需要将顶点加入再跑凸包即可,那么对于光滑的圆形我们如何加入节点呢 ?
其实不难想到,或许我们只需要平均的取每个圆上 T 个节点将其加入来跑凸包,可以取正好卡时间复杂度的节点数量,毕竟 T 越大答案越精准
------------
这里引入一个很有意思的结论
T 每增大一倍,求得的周长的误差(即与精确周长之差的绝对值)缩小到原来的四分之一。(线性插值的二阶收敛性质)
------------
观察此题精度卡在
实测只需要每个圆只取 2500 个点就可以了
取到 5000 更稳
------------
如何均匀取圆心为
的圆上的 T 个点呢 ? 下面给出一个可用的方式
循环 i 从 1 到 T 每次加入点 ![P\left ( x_i,y_i \right )](https://latex.csdn.net/eq?P%5Cleft%20%28%20x_i%2Cy_i%20%5Cright%20%29)
其中
如此,整道题的难点就全部完成了,可以愉快的切掉这道水题
接下来,上代码!!!
码风有些奇怪但是自认为很帅
#include<bits/stdc++.h>
#define int long long
using namespace std;
const double pi=acos(-1);
const double eps=1e-12;
const int N=1e5+5;
int dcmp(double x)
{
if(fabs(x)<eps)return 0;
if(x<0)return -1;
return 1;
}
struct point{
double x,y;
point(double x=0,double y=0):x(x),y(y){};
double lenght()
{
return sqrt(x*x+y*y);
}
}p[N],ch[N];
point operator-(const point &a,const point &b)
{
return point(a.x-b.x,a.y-b.y);
}
bool operator<(const point &a,const point &b)
{
return a.x<b.x||(a.x==b.x&&a.y<b.y);
}
double cross(point a,point b)
{
return a.x*b.y-a.y*b.x;
}
int G(int n)
{
sort(p+1,p+n+1);
int m=0;
for(int i=1;i<=n;i++)
{
while(m>=2&&dcmp(cross(ch[m]-ch[m-1],p[i]-ch[m-1]))>=0)m--;
ch[++m]=p[i];
}
int k=m;
for(int i=n-1;i>=1;i--)
{
while(m>k&&dcmp(cross(ch[m]-ch[m-1],p[i]-ch[m-1]))>=0)m--;
ch[++m]=p[i];
}
if(m==1)return 1;
return m-1;
}
char s[N];
signed main()
{
int n;
scanf("%lld",&n);
scanf("%s",s+1);
int pl=0;
for(int i=1;i<=strlen(s+1);i++)
{
if(s[i]=='T')
{
p[++pl].x=i*1.0;
p[pl].y=0;
p[++pl].x=i*1.0+1;
p[pl].y=0;
p[++pl].x=i*1.0+0.5;
p[pl].y=sqrt(3)/2;
}
if(s[i]=='S')
{
p[++pl].x=i*1.0;
p[pl].y=0;
p[++pl].x=i*1.0+1;
p[pl].y=0;
p[++pl].x=i*1.0;
p[pl].y=1;
p[++pl].x=i*1.0+1;
p[pl].y=1;
}
if(s[i]=='C')
{
int T=2500;
for(int v=1;v<=T;v++)
{
p[++pl]={i*1.0+0.5+0.5*cos((2*pi*v)/T),0.5+0.5*sin((2*pi*v)/T)};
}
}
}
int m=G(pl);
double len=0;
for(int i=1;i<=m;i++)
{
len+=(ch[i+1]-ch[i]).lenght();
}
printf("%.7lf",len);
return 0;
}