ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P3829 [SHOI2012]信用卡凸包

2019-04-03 12:38:42  阅读:289  来源: 互联网

标签:return seta Point int double 凸包 Vec SHOI2012 P3829


思路

注意到结果就是每个信用卡边上的四个圆心的凸包周长+一个圆的周长

然后就好做了

注意凸包中如果存在叉积为0的点也要pop,否则可能会错。

几个简单的向量的式子

\[ a*b=(x_1y_1+ x_2y_2) \]
\[ a\times b=(x_1y_2- x_2y_1) \]
逆时针旋转\(\theta\)度
\[ x'=xcos\theta-ysin\theta\\ y'=xsin\theta+ycos\theta \]

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
struct Vec{
    double x,y;
    Vec(){};
    Vec(double xx,double yy){
        x=xx;
        y=yy;
    }
    double mul(Vec b){
        return x*b.x+y*b.y;
    }
    double cross(Vec b){
        return x*b.y-y*b.x;
    }
    Vec rev(double seta){
        return Vec(x*cos(seta)-y*sin(seta),x*sin(seta)+y*cos(seta));
    }
};
struct Point{
    double x,y;
    Point(){};
    Point(double xx,double yy){
        x=xx;
        y=yy;
    }
    Point operator + (Point b){
        return Point(x+b.x,y+b.y);
    } 
    Point operator + (Vec b){
        return Point(x+b.x,y+b.y);
    } 
    Vec operator - (Point b){//b-a a->b
        return Vec(b.x-x,b.y-y);
    }
    Point rev(Point b,double seta){//a 绕 b
        return b+((Point(x,y))-b).rev(seta);
    }
    double dist(Point a){
        return sqrt((x-a.x)*(x-a.x)+(y-a.y)*(y-a.y));
    }
};
struct Stack{
    int data[400100],topx=0;
    void push(int x){
        data[++topx]=x;
    }
    void pop(void){
        topx--;
    }
    int top(void){
        return data[topx];
    }
    int Setop(void){
        return data[topx-1];
    }
};
Point a[400100];
Stack S;
bool cmp(Point x,Point y){
    return (x-a[1]).cross(y-a[1])>0||((x-a[1]).cross(y-a[1])==0&&x.dist(a[1])>y.dist(a[1]));
}
int n,cnt;
double ax,bx,rx,ans=0;
int main(){
    scanf("%d",&n);
    scanf("%lf %lf %lf",&ax,&bx,&rx);
    for(int i=1;i<=n;i++){
        double x,y,seta;
        scanf("%lf %lf %lf",&x,&y,&seta);
        a[++cnt]=Point(x-bx/2+rx,y+ax/2-rx).rev(Point(x,y),seta);
        a[++cnt]=Point(x-bx/2+rx,y-ax/2+rx).rev(Point(x,y),seta);
        a[++cnt]=Point(x+bx/2-rx,y+ax/2-rx).rev(Point(x,y),seta);
        a[++cnt]=Point(x+bx/2-rx,y-ax/2+rx).rev(Point(x,y),seta);
    }
    // for(int i=1;i<=cnt;i++)
    //  printf("%lf %lf\n",a[i].x,a[i].y);
    int pos=1;
    for(int i=2;i<=cnt;i++)
        if(a[i].x<a[pos].x||(a[i].x==a[pos].x&&a[i].y<a[pos].y))
            pos=i;
    swap(a[1],a[pos]);
    sort(a+2,a+cnt+1,cmp);
    S.push(1);
    S.push(2);
    for(int i=3;i<=cnt;i++){
        while(S.topx>0&&(a[S.Setop()]-a[S.top()]).cross(a[S.Setop()]-a[i])<=0){
            S.pop();
        }
        S.push(i);
    }
    int tt=S.top();
    while(S.topx>1){
        ans+=a[S.top()].dist(a[S.Setop()]);
        S.pop();
    }
    ans+=a[S.top()].dist(a[tt]);
    ans+=2*acos(-1.0)*rx;
    printf("%.2lf\n",ans);
    return 0;
}

标签:return,seta,Point,int,double,凸包,Vec,SHOI2012,P3829
来源: https://www.cnblogs.com/dreagonm/p/10648046.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有