bzoj2829: 信用卡凸包(凸包)

題面在這裏

做法

//最近怎麼…..手賤連連啊..有點不妙啊;_;

思路是將所有圓心求一個凸包,再加上圓的周長。

記錯誤:1.注意精度問題。 2.注意1不要寫成i。

代碼

#include<bits/stdc++.h>
#define rep(i,x,y) for (int i=(x);i<=(y);i++)
#define ll long long
#define ld long double
#define sqr(x) ((x)*(x))
using namespace std;
const ld pi=acos(-1);
const ld eps=1e-8;
#define N 100005
int n,m,top;ld A,B,R,ans=0;
struct node{ld x,y;node(){}node(ld x_,ld y_){x=x_,y=y_;}}a[N],stk[N];
node rot(node x,ld alp){return node(x.x*cos(alp)-x.y*sin(alp),x.y*cos(alp)+x.x*sin(alp));}//向量x逆時針旋轉alp度
node operator + (node x,node y){return node(x.x+y.x,x.y+y.y);}
node operator - (node x,node y){return node(x.x-y.x,x.y-y.y);}
ld cross(node A,node B){return A.x*B.y-A.y*B.x;}
ld dot(node A){return sqrt(sqr(A.x)+sqr(A.y));}
ld getlen(node A){return dot(A);}
const bool cmp(const node x,const node y){
    if (fabs(cross(x-a[1],y-a[1]))<eps) return getlen(x-a[1])<getlen(y-a[1]);
    return cross(x-a[1],y-a[1])>0;
}
void graham(){
    rep (i,1,n) if (a[i].y<a[1].y||a[i].y==a[1].y&&a[i].x<a[1].x) swap(a[i],a[1]);
    sort(&a[2],&a[n+1],cmp);
    stk[1]=a[1];stk[2]=a[2];top=2;
    rep (i,3,n){
        while (top>1&&cross(stk[top]-stk[top-1],a[i]-stk[top-1])<=eps) top--;
        stk[++top]=a[i];
    }
}
int main(){
    double A_,B_,R_;
    scanf("%d%lf%lf%lf",&n,&A_,&B_,&R_);A=A_,B=B_,R=R_;A-=2*R;B-=2*R;
    rep (i,1,n){
        double x,y,alp;scanf("%lf%lf%lf",&x,&y,&alp);
        node tmp(x,y);
        a[++m].x=x-B/2.;a[m].y=y-A/2.;a[m]=tmp+rot(a[m]-tmp,alp);
        a[++m].x=x-B/2.;a[m].y=y+A/2.;a[m]=tmp+rot(a[m]-tmp,alp);
        a[++m].x=x+B/2.;a[m].y=y-A/2.;a[m]=tmp+rot(a[m]-tmp,alp);
        a[++m].x=x+B/2.;a[m].y=y+A/2.;a[m]=tmp+rot(a[m]-tmp,alp);
    }
    n=m;graham();ans=0;
    rep (i,1,top) ans+=getlen(stk[i%top+1]-stk[(i+1)%top+1]);
    ans+=pi*2*R;
    printf("%.2lf\n",(double)ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章