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 }
2016-12-13 18:38:01