【BZOJ 2829】 2829: 信用卡凸包 (凸包)

2829: 信用卡凸包

Description

Input

Output

Sample Input

2
6.0 2.0 0.0
0.0 0.0 0.0
2.0 -2.0 1.5707963268

Sample Output

21.66

HINT


本样例中的2张信用卡的轮廓在上图中用实线标出,如果视1.5707963268为

Pi/2(pi为圆周率),则其凸包的周长为16+4*sqrt(2)

 

 

【分析】

  乍一看还是不会做hh。

  把那个圆拿出来,做凸包,最后再加一个圆形的周长就好了。

  至于为什么,我还是看黄学长博客的,只能意会一下,不会证明,但是我觉得应该是把凸包向外平移然后凸多边形外角和等于360度,说明外面可以拼成一个完整的圆吧。

  所以一开始a-=2*r,b-=2*r。

 

  说一下旋转那部分,傻傻地画图搞了很久,用向量就会很方便。

  设a和b的夹角是y,要旋转的角是x。

  假设中心点在原点,最后再平移。一开始不旋转的时候是(b/2,a/2)

  设r*r=a*a+b*b

  新点(r*cos(x+y),r*sin(x+y)) -> (r*cosx*cosb-r*sinx*sinb,r*sinx*sinb+r*cosx*sinb) -> (b/2*cosx-a/2*sinx)

  其他三个点类似。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<cmath>
  7 using namespace std;
  8 #define Maxn 400010
  9 
 10 const double eps=0.00001;
 11 const double pi=3.14159265;
 12 
 13 struct P
 14 {
 15     double x,y;
 16 }t[Maxn],w[Maxn];
 17 int len,wl;
 18 double a,b,r;
 19 
 20 P operator - (P a,P b)
 21 {
 22     P tt;
 23     tt.x=a.x-b.x;tt.y=a.y-b.y;
 24     return tt;
 25 }
 26 
 27 /*P rot(P x,double d,double c)
 28 {
 29     P nw;
 30     nw.x=x.x+d*cos(c);
 31     nw.y=x.y+d*sin(c);
 32     return nw;
 33 }*/
 34 
 35 P rot(double x,double y,P nw,double c)
 36 {
 37     P ans;
 38     ans.x=x+nw.x*cos(c)-nw.y*sin(c);
 39     ans.y=y+nw.x*sin(c)+nw.y*cos(c);
 40     return ans;
 41 }
 42 
 43 void make_p(double x,double y,double c)
 44 {
 45     P nw;
 46     nw.x=b/2,nw.y=a/2; t[++len]=rot(x,y,nw,c);
 47     nw.x=-b/2,nw.y=a/2; t[++len]=rot(x,y,nw,c);
 48     nw.x=b/2,nw.y=-a/2; t[++len]=rot(x,y,nw,c);
 49     nw.x=-b/2,nw.y=-a/2; t[++len]=rot(x,y,nw,c);
 50     /*for(int k=0;k<4;k++)
 51     {
 52         nw.x=x;nw.y=y;
 53         P now=rot(nw,b/2,k*pi/2+c);
 54         t[++len]=rot(now,a/2,(k+1)*pi/2+c);
 55         double tt;
 56         tt=a;a=b;b=tt;
 57     }*/
 58 }
 59 
 60 double myabs(double x) {return x>0?x:-x;}
 61 
 62 int fbs(double x)
 63 {
 64     if(myabs(x)<=eps) return 0;
 65     else return x>0?1:-1;
 66 }
 67 
 68 bool cmp(P x,P y) {return fbs(x.x-y.x)==0?(x.y<y.y):(x.x<y.x);}
 69 double Dot(P x,P y) {return x.x*y.x+x.y*y.y;}
 70 double Cross(P x,P y) {return x.x*y.y-x.y*y.x;}
 71 
 72 void chull()
 73 {
 74     sort(t+1,t+1+len,cmp);
 75     wl=0;
 76     for(int i=1;i<=len;i++)
 77     {
 78         while(wl>1&&Cross(w[wl]-w[wl-1],t[i]-w[wl])<=0) wl--;
 79         w[++wl]=t[i];
 80     }
 81     int k=wl;
 82     for(int i=len-1;i>=1;i--)
 83     {
 84         while(wl>k&&Cross(w[wl]-w[wl-1],t[i]-w[wl])<=0) wl--;
 85         w[++wl]=t[i];
 86     }
 87     wl--;
 88 }
 89 
 90 double get_length()
 91 {
 92     double ans=0;
 93     for(int i=1;i<wl;i++)
 94     {
 95         ans+=sqrt(Dot(w[i]-w[i+1],w[i]-w[i+1]));
 96     }
 97     ans+=sqrt(Dot(w[wl]-w[1],w[wl]-w[1]));
 98     return ans;
 99 }
100 
101 int main()
102 {
103     int n;
104     scanf("%d",&n);
105     scanf("%lf%lf%lf",&a,&b,&r);a-=2*r;b-=2*r;
106     len=0;
107     for(int i=1;i<=n;i++)
108     {
109         double x,y,c;
110         scanf("%lf%lf%lf",&x,&y,&c);
111         make_p(x,y,c);
112     }
113     chull();
114     double ans=get_length();
115     ans+=2*r*pi;
116     printf("%.2lf\n",ans);
117     return 0;
118 }
View Code

 

 

2016-12-13 18:38:01

转载于:https://www.cnblogs.com/Konjakmoyu/p/6171045.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值