Bzoj2829 信用卡凸包

Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special Judge
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

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 */

 

posted @ 2017-03-03 11:38  SilverNebula  阅读(328)  评论(0编辑  收藏  举报
AmazingCounters.com