Bzoj2829 信用卡凸包
Submit: 333 Solved: 155
Description
Input
Output
Sample Input
2
6.0 2.0 0.0
0.0 0.0 0.0
2.0 -2.0 1.5707963268
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)
Source
几何 凸包
把矩形边长减去圆的直径,得到有效边长。计算出每个矩形的四个点,找到凸包,再加上一个圆的周长就是答案。
迷之WA,注释掉的旋转方法不知为何不对(小样例居然都过了)
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const double Pi=acos(-1.0); 10 const int mxn=100010; 11 struct point{ 12 double x,y; 13 point operator - (point rhs){return (point){x-rhs.x,y-rhs.y};} 14 point operator + (point rhs){return (point){x+rhs.x,y+rhs.y};} 15 }p[mxn]; 16 17 double cross(point a,point b){return a.x*b.y-a.y*b.x;} 18 double dist(point a,point b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);} 19 int cmp(point a,point b){ 20 double tmp=cross(a-p[1],b-p[1]); 21 return (tmp<0 || (tmp==0 && dist(a,p[0])>dist(b,p[0]))); 22 } 23 int cmp2(point a,point b,point p){ 24 double tmp=cross(a-p,b-p); 25 return (tmp<0 || (tmp==0 && dist(a,p)>=dist(b,p))); 26 } 27 point rotate(point a,double angle){ 28 return (point){a.x*cos(angle)-a.y*sin(angle),a.x*sin(angle)+a.y*cos(angle)}; 29 } 30 point move(point a,double len,double an){ 31 return (point){a.x+len*cos(an),a.y+len*sin(an)}; 32 } 33 int n; 34 double a,b,r; 35 double x,y,th; 36 int st[mxn],top; 37 int main(){ 38 int i,j; 39 scanf("%d",&n); 40 scanf("%lf%lf%lf",&a,&b,&r); 41 a-=2*r;b-=2*r; 42 top=0; 43 for(i=1;i<=n;i++){ 44 scanf("%lf%lf%lf",&x,&y,&th); 45 for(j=1;j<=4;j++) 46 { 47 point tmp=move((point){x,y},b/2,th+Pi*(j-1)/2); 48 p[++top]=move(tmp,a/2,th+Pi*j/2); 49 swap(a,b); 50 } 51 // point tmp; 52 /* 53 tmp.x=a/2;tmp.y=b/2;p[++top]=(point){x,y}+rotate(tmp,th); 54 tmp.x=-a/2;tmp.y=b/2;p[++top]=(point){x,y}+rotate(tmp,th); 55 tmp.x=a/2;tmp.y=-b/2;p[++top]=(point){x,y}+rotate(tmp,th); 56 tmp.x=-a/2;tmp.y=-b/2;p[++top]=(point){x,y}+rotate(tmp,th); 57 */ 58 } 59 n=top;top=0; 60 int s=1; 61 for(i=1;i<=n;i++){ 62 if(p[i].x<p[s].x || (p[i].x==p[s].x && p[i].y<p[s].y))s=i; 63 } 64 swap(p[s],p[1]); 65 sort(p+2,p+n+1,cmp); 66 p[n+1]=p[1]; 67 n++; 68 for(i=1;i<=n;i++){ 69 while(top>1 && cmp2(p[i],p[st[top]],p[st[top-1]]))top--; 70 st[++top]=i; 71 } 72 double ans=0; 73 ans+=Pi*2*r; 74 for(i=1;i<top;i++){ 75 ans+=sqrt(dist(p[st[i]],p[st[i+1]])); 76 } 77 printf("%.2lf\n",ans); 78 return 0; 79 } 80 /* 81 5 82 12.0 6.0 2.0 83 0.0 0.0 0.0 84 1 1 1 85 2 2 1.5707963268 86 1 7 0 87 2.0 -2.0 1.5707963268 88 */
本文为博主原创文章,转载请注明出处。