P3829 [SHOI2012]信用卡凸包

题意

通过观察发现答案为一个整圆+所有除去圆弧的四个顶点形成的凸包的周长,于是直接套模板就好了。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
const double eps=1e-8;
const double Pi=acos(-1.0);
int n,tot,top;
int sta[maxn];
double H,L,R,ans;
struct Point{
    double x,y;
    Point operator+(const Point& a)const{return (Point){x+a.x,y+a.y};}
    Point operator-(const Point& a)const{return (Point){x-a.x,y-a.y};}
    Point operator*(const double& k){return (Point){x*k,y*k};}
    Point operator/(const double& k){return (Point){x/k,y/k};}
    double operator*(const Point& a)const{return x*a.y-y*a.x;}
    double operator&(const Point& a)const{return x*a.x+y*a.y;}
}p[maxn<<2];
inline int dcmp(double x)
{
	if(fabs(x)<=eps)return 0;
	return x<0?-1:1;
}
inline Point turn(Point a,double theta){return (Point){a.x*cos(theta)-a.y*sin(theta),a.x*sin(theta)+a.y*cos(theta)};}
inline double dis(double x1,double y1,double x2,double y2){return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}
inline bool cmp(Point a,Point b){return a.x==b.x?a.y<b.y:a.x<b.x;}
int main()
{
	scanf("%d%lf%lf%lf",&n,&H,&L,&R);
	for(int i=1;i<=n;i++)
	{
		double x,y,theta;scanf("%lf%lf%lf",&x,&y,&theta);
		x+=eps,y+=eps,theta+=eps;
		double tmpx=L-2*R,tmpy=H-2*R;
		p[++tot]=turn((Point){-tmpx/2.0,tmpy/2.0},theta)+(Point){x,y};
		p[++tot]=turn((Point){tmpx/2.0,tmpy/2.0},theta)+(Point){x,y};
		p[++tot]=turn((Point){tmpx/2.0,-tmpy/2.0},theta)+(Point){x,y};
		p[++tot]=turn((Point){-tmpx/2.0,-tmpy/2.0},theta)+(Point){x,y};
	}
	sort(p+1,p+tot+1,cmp);
	for(int i=1;i<=tot;i++)
	{
		while(top>1&&dcmp((p[sta[top]]-p[sta[top-1]])*(p[i]-p[sta[top]]))<=0)top--;
		sta[++top]=i;
	}
	int tmp=top;
	for(int i=tot-1;i;i--)
	{
		while(top>tmp&&dcmp((p[sta[top]]-p[sta[top-1]])*(p[i]-p[sta[top]]))<=0)top--;
		sta[++top]=i;
	}
	for(int i=1;i<top;i++)ans+=dis(p[sta[i]].x,p[sta[i]].y,p[sta[i+1]].x,p[sta[i+1]].y);
	printf("%.2lf",ans+2*Pi*R);
	return 0;
} 
原文地址:https://www.cnblogs.com/nofind/p/12169556.html