zoukankan      html  css  js  c++  java
  • BZOJ2829信用卡凸包——凸包

    题目描述

    输入

    输出

    样例输入

    2
    6.0 2.0 0.0
    0.0 0.0 0.0
    2.0 -2.0 1.5707963268

    样例输出

    21.66

    提示


    本样例中的2张信用卡的轮廓在上图中用实线标出,如果视1.5707963268为
    Pi/2(pi为圆周率),则其凸包的周长为16+4*sqrt(2)

    我们先将每个信用卡看成是由四个圆心组成的矩形,那么凸包就是所有圆心形成的凸包。现在每个圆心往外扩展为一个圆,那么就是用凸包来包住所有的圆,而新的凸包的直边部分就是原凸包对应边往外平移得到。对于曲面部分,因为一个凸多边形外角和为360度,所以曲面部分就是一个圆的周长。直接求所有圆心形成凸包的周长再加上一个圆的周长即可。

    #include<set>
    #include<map>
    #include<queue>
    #include<stack>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<bitset>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    const double pi=acos(-1.0);
    struct lty
    {
    	double x,y;
    	lty(double X=0,double Y=0){x=X,y=Y;}
    }a[40010];
    lty operator -(lty a,lty b){return lty(a.x-b.x,a.y-b.y);}
    double operator *(lty a,lty b){return a.x*b.y-b.x*a.y;}
    int st[40010];
    int vis[40010];
    int top;
    int n;
    int cnt;
    double x,y,r;
    double X,Y,R;
    double ans;
    lty res;
    bool cmp(lty a,lty b)
    {
    	return a.x==b.x?a.y<b.y:a.x<b.x;
    }
    int main()
    {
    	scanf("%d",&n);
    	scanf("%lf%lf%lf",&X,&Y,&R);
    	X=X/2-R,Y=Y/2-R;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lf%lf%lf",&x,&y,&r);
    		a[++cnt]=lty(x+Y*cos(r)+X*sin(r),y+Y*sin(r)-X*cos(r));
    		a[++cnt]=lty(x-Y*cos(r)+X*sin(r),y-Y*sin(r)-X*cos(r));
    		a[++cnt]=lty(x+Y*cos(r)-X*sin(r),y+Y*sin(r)+X*cos(r));
    		a[++cnt]=lty(x-Y*cos(r)-X*sin(r),y-Y*sin(r)+X*cos(r));
    	}
    	sort(a+1,a+1+cnt,cmp);
    	st[++top]=1;
    	for(int i=2;i<=cnt;i++)
    	{
    		while(top>1&&(a[st[top]]-a[st[top-1]])*(a[i]-a[st[top]])<=0)
    		{
    			vis[st[top--]]=0;
    		}
    		vis[i]=1;
    		st[++top]=i;
    	}
    	int lim=top;
    	for(int i=cnt-1;i>=1;i--)
    	{
    		if(!vis[i])
    		{
    			while(top>lim&&(a[st[top]]-a[st[top-1]])*(a[i]-a[st[top]])<=0)
    			{
    				vis[st[top--]]=0;
    			}
    			vis[i]=1;
    			st[++top]=i;
    		}
    	}
    	for(int i=1;i<top;i++)
    	{
    		res=a[st[i+1]]-a[st[i]];
    		ans+=sqrt(res.x*res.x+res.y*res.y);
    	}
    	printf("%.2f",ans+2*pi*R);
    }
  • 相关阅读:
    [转]Android Permission(授权)大全
    ubuntu改中文
    [转]dip, dp, px, sp区别
    【转】关于Android4.0 emulatorarm.exe应用程序错误,内存不能为"read"问题解决方法
    SharedPreferences 的用法
    [转]深入研究java.lang.ThreadLocal类
    [转]Android 中Parcelable的作用
    HierarchyView
    使用Silverlight Toolkit中的主题(Theme)
    Split参数StringSplitOptions.RemoveEmptyEntries的使用
  • 原文地址:https://www.cnblogs.com/Khada-Jhin/p/10609711.html
Copyright © 2011-2022 走看看