zoukankan      html  css  js  c++  java
  • 题解 P3829 【[SHOI2012]信用卡凸包】

    Link

    P3829 [SHOI2012]信用卡凸包

    Solve

    话说这道题挺良心的,算法在题目上都写出来了,我们就从凸包来考虑。

    我们发现有圆的地方很难处理,画了几个图后发现,相比之下,圆的地方加起来就是一个整圆,问题是怎么来证明。

    这里借用一下神仙jun头吉吉的图

    我们观察到多出来的部分和圆肯定是相切的,比如(DK)切与圆(C),所以(∠BCD+∠BZD=180°)

    多边形内角和为(sumlimits_{i=1}^nalpha_i=180 imes (n-2))

    所以所有圆心角之和为$180 imes n - sumlimits_{i=1}^nalpha_i =180 imes n -180 imes (n-2) = 360 = 2pi $

    答案即为一个圆的周长+圆心构成的凸包的周长。

    所以这道题就和板子一样了

    code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=100005;
    int n,top,m;
    double ans=0,A,B,R,l,phi;
    struct AS{
    	double x,y;
    }a[maxn],p[maxn];
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    	return ret*f;
    }
    double check(AS A1,AS A2,AS B1,AS B2){
    	return (A2.x-A1.x)*(B2.y-B1.y)-(B2.x-B1.x)*(A2.y-A1.y);
    }
    double d(AS A,AS B){
    	return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
    }
    bool cmp(AS x,AS y){
    	double tmp=check(a[1],x,a[1],y);
    	if(tmp>0)return 1;
    	if(tmp==0&&(d(a[1],x)<d(a[1],y)))return 1;
    	return 0;
    }
    void add(double x,double y){
    	n++;	
    	a[n].x=x;a[n].y=y;
    	if(a[n].y<a[1].y)swap(a[1],a[n]);
    }
    int main(){
    	freopen("P3829.in","r",stdin);
    	freopen("P3829.out","w",stdout);
    	scanf("%d%lf%lf%lf",&m,&A,&B,&R);A-=2*R;B-=2*R;
    	l=sqrt(A*A+B*B)/2;
    	phi=atan(A/B);
    	for(int i=1;i<=m;i++){
    		double x,y,theta;
    		scanf("%lf%lf%lf",&x,&y,&theta);
    		double dx=cos(theta+phi)*l;
    		double dy=sin(theta+phi)*l;
    		add(x+dx,y+dy);
    		add(x-dx,y-dy);
    		dx=cos(theta-phi)*l;
    		dy=sin(theta-phi)*l;
    		add(x+dx,y+dy);
    		add(x-dx,y-dy);
    	}
    	sort(a+2,a+1+n,cmp);
    	p[top=1]=a[1];
    	for(int i=2;i<=n;i++){
    		while(top>1&&check(p[top-1],p[top],p[top],a[i])<=0)top--;
    		top++;
    		p[top]=a[i];
    	}
    	p[++top]=p[1];
    	for(int i=1;i<top;i++){
    		ans+=d(p[i],p[i+1]);
    	}
    	printf("%.2lf
    ",ans+3.141592653589793*2*R);
    	return 0;
    }
    
  • 相关阅读:
    句柄
    类,方法,抽象方法,接口
    Enum类型
    String 为什么是不可变的
    大数据怎么排序
    oracle创建表空间 导入数据库
    eclipse常见小问题
    eclipse创建项目
    存储过程
    在VMware通过挂载系统光盘搭建本地yum仓库
  • 原文地址:https://www.cnblogs.com/martian148/p/13541082.html
Copyright © 2011-2022 走看看