题目分析
类似于凸包模板的一道题。
我们循序渐进地考虑,当半径 \(r=0\) 时,显然是一个二位凸包模板。
接着我们将圆弧加进去,仔细观察发现,我们构造出的凸包中的直线部分就是将圆心之间连起来的长度,而一个圆的贡献就是 \(\dfrac{1}{4}\) 个圆弧,四个圆贡献加起来正好就是一个圆的周长。
然后将模板改一下就做完了。
贴上代码
#include<bits/stdc++.h>
#define int long long
#define ok puts("Yes")
#define no puts("-1")
#define pi acos(-1)
#define at atan(A/B)
using namespace std;
int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-48;
c=getchar();
}
return x*f;
}
const int maxn=2e5+5;
const double eps=1e-18;
double equ(double x){
if(fabs(x)<eps) return 0;
if(x>=0) return 1;
else return -1;
}
int n;
int cnt;
double a,b,r,x,y,op;
double A,B,C;
double ans;
struct point{
double x,y;
point(double _x=0,double _y=0):x(_x),y(_y){}
point operator + (const point &pt){return point(x+pt.x,y+pt.y);}
point operator - (const point &pt){return point(x-pt.x,y-pt.y);}
}p[maxn];
bool cmp(point p,point q){
if(equ(p.x-q.x)==0) return p.y<q.y;
else return p.x<q.x;
}
struct my_stack{
point stk[maxn];int sz=0;
void push(point x){stk[sz++]=x;}
point top(){return stk[sz-1];}
point sec_top(){return stk[sz-2];}
int size(){return sz;}
void pop(){sz--;}
}st;
// bool slope(int aa,int b,int c){return (p[aa].y-p[b].y)*(p[b].x-p[c].x)>(p[aa].x-p[b].x)*(p[b].y-p[c].y);}
double dis(point a,point b){return sqrt((a.y-b.y)*(a.y - b.y)+(a.x-b.x)*(a.x-b.x));}
double cross(point a,point b){return a.x*b.y-a.y*b.x;}
double dot(point a,point b){return a.x*b.x+a.y*b.y;}
double len(point a){return sqrt(dot(a,a));}
double angle(point a,point b){return acos(dot(a,b)/len(a)/len(b));}
inline void init(){
n=read();
scanf("%lf%lf%lf",&a,&b,&r);
A=a-2.0*r;B=b-2.0*r;C=sqrt(A*A+B*B)/2.0;
for(register int i=1;i<=n;++i){
scanf("%lf%lf%lf",&x,&y,&op);
double xx=cos(op+at)*C,yy=sin(op+at)*C;
p[++cnt].x=x+xx;p[cnt].y=y+yy;
p[++cnt].x=x-xx;p[cnt].y=y-yy;
xx=cos(op-at)*C,yy=sin(op-at)*C;
p[++cnt].x=x+xx;p[cnt].y=y+yy;
p[++cnt].x=x-xx;p[cnt].y=y-yy;
}
sort(p+1,p+cnt+1,cmp);
}
signed main(){
init();
for(register int i=1;i<=cnt;++i){
while(equ(cross(st.top()-st.sec_top(),p[i]-st.sec_top()))==-1&&st.size()>1) st.pop();
st.push(p[i]);
}
int siz=st.size();
for(register int i=cnt-1;i>=1;--i){
while(equ(cross(st.top()-st.sec_top(),p[i]-st.sec_top()))==-1&&st.size()>siz) st.pop();
st.push(p[i]);
}
for(register int i=0;i<st.size()-1;++i) ans+=dis(st.stk[i],st.stk[i+1]);
ans+=2.0*pi*r;
printf("%.2lf",ans);
}
标签:return,pt,point,int,double,st,题解,P3829
From: https://www.cnblogs.com/yizhixiaoyun/p/17034319.html