题目描述
输入描述
输出描述
输入样例1
4
TSTC
输出样例1
9.088434417
输入样例2
3
SCT
输出样例2
7.50914177324
题目大意: 给定若干个正三角形,正方形,圆形排列成一行,求包围他们一周所需要的最小长度。
由于知识淡薄,写题的时候并不知道知识点是凸包,但显然该题纯用数学也是可以计算的。
本题中不难看出,需要进行特殊处理的组合是当边界为三角形,而中端存在正方形或圆形,此时两种图形之间的最优连线为由边界三角形的顶点至正方形的顶点,或圆的切点。
其中,对于三角形与圆之间的连线除了切线外,还有切点到圆顶部的弧长,网上搜索公式代入即可。
而当序列全为三角形时,连线所呈现出的将是一个等腰梯形。
参考代码
#include <bits/stdc++.h>
using namespace std;
#define PI acos(-1)
const double C=0.5*sqrt(3.0);
double sanyuan(int n){
double a=atan((C-0.5)/n);
double b=asin(0.5/sqrt(n*n+(C-0.5)*(C-0.5)))-a;;
double c=0.5*PI-a-b;
return 0.5*(tan(c)+b);
}
int main(){
// double h=sqrt(0.75);
// double ans=6.5+sqrt((1-h)*(1-h)+1);
// printf("%.9lf",ans);
int n;cin>>n;
double bian=1;
string s;cin>>s;
if(n==1){
if(s[0]=='T')
printf("%.9lf\n",bian*3.0);
else if(s[0]=='S')
printf("%.9lf\n",bian*4.0);
else if(s[0]=='C')
printf("%.9lf\n",1.0*bian*PI);
return 0;
}
int num=0,nnum=0;
if(s[0]=='T')
for(int i=0;i<n;i++){
if(s[i]=='T')num++;
else break;
}
if(s[n-1]=='T')
for(int i=n-1;i>=0;i--){
if(s[i]=='T')nnum++;
else break;
}
// cout<<num<<' '<<nnum<<endl;
double h=sqrt(0.75);
if(num==n||nnum==n){
//全是三角
printf("%lf\n",2.0*n+1.0);
}
else{
//和三角组合求一半
double ans=0;
if(num!=0||nnum!=0){
if(n-num-nnum-1>0) //zhongjian
ans+=(n-num-nnum-1)*2;
if(num!=0){
if(s[num]=='S'){
//连接第一个
ans=ans+sqrt((num-0.5)*(num-0.5)+(1-h)*(1-h))+2+num;
}else{
ans=ans+sanyuan(num)+1.5+num;
}
}
if(nnum!=0){
if(s[n-nnum-1]=='S'){
ans=ans+sqrt((nnum-0.5)*(nnum-0.5)+(1-h)*(1-h))+2+nnum;
}else{
ans=ans+sanyuan(nnum)+1.5+nnum;
}
}
if(s[0]=='S'){
ans+=2;
}else if(s[0]=='C'){
ans+=PI/2;
}
if(s[n-1]=='S'){
ans+=2;
}else if(s[n-1]=='C'){
ans+=PI/2;
}
printf("%.9lf\n",ans);
}
else{
//两边均不三角形
ans=(n-2)*2;
if(s[0]=='S'){
ans+=3;
}else if(s[0]=='C'){
ans+=(1+PI/2);
}
if(s[n-1]=='S'){
ans+=3;
}
if(s[n-1]=='C'){
ans+=(1+PI/2);
}
printf("%.9lf\n",ans);
}
}
return 0;
}