Luogu-3829 [SHOI2012]信用卡凸包

这道题的转化很巧妙,可以把信用卡四个角的圆心看做平面上的点来做凸包,\(ans\)就是凸包周长加上一个圆的周长

// luogu-judger-enable-o2
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e5+100;
const double Pi=3.14159265358979323846;
struct Point{
    double x,y;
    Point(double xx=0,double yy=0){
        x=xx,y=yy;
    }
    bool operator < (Point a) const{
        return x==a.x?y<a.y:x<a.x;
    }
    bool operator == (Point a) const{
        return x==a.x&&y==a.y;
    }
}a[maxn],b[maxn],c;
struct Vector{
    double x,y;
    Vector(double xx=0,double yy=0){
        x=xx,y=yy;
    }
}zhy[4];
int dcmp(double x){return fabs(x)<1e-9?0:(x>0?1:-1);}
Vector operator - (Point a,Point b){return Vector(a.x-b.x,a.y-b.y);}
Point operator + (Point a,Vector b){return Point(a.x+b.x,a.y+b.y);}
double operator * (Vector a,Vector b){return a.x*b.y-a.y*b.x;}
Vector rotate(Vector a,double p){return Vector(a.x*cos(p)-a.y*sin(p),a.x*sin(p)+a.y*cos(p));}
double dot(Vector a,Vector b){return a.x*b.x+a.y*b.y;}
double len(Vector a){return sqrt(dot(a,a));}
int n,m,tot;
double r,du;
void tb(Point *p,int n,Point *q,int &m){
    sort(p+1,p+n+1);
    q[m=1]=p[1];
    if(n==1) return;
    for(int i=2;i<=n;i++){
        while(m>1&&dcmp((q[m]-q[m-1])*(p[i]-q[m-1]))<=0)
            m--;
        q[++m]=p[i];
    }
    int k=m;
    for(int i=n-1;i>=1;i--){
        while(m>k&&dcmp((q[m]-q[m-1])*(p[i]-q[m-1]))<=0)
            m--;
        q[++m]=p[i];
    }
    m--;
}
double C(Point *p,int n){
    if(n==1) return 0;
    double tot=0;
    for(int i=1;i<n;i++)
        tot+=len(p[i+1]-p[i]);
    return tot+len(p[n]-p[1]);
}
int main(){
    scanf("%d",&m);
    scanf("%lf%lf%lf",&zhy[0].y,&zhy[0].x,&r);
    zhy[0].x/=2,zhy[0].y/=2;
    zhy[0].x-=r,zhy[0].y-=r;
    zhy[1]=zhy[2]=zhy[3]=zhy[0];
    zhy[1].x*=-1,zhy[2].x*=-1,zhy[2].y*=-1,zhy[3].y*=-1;
    for(int i=1;i<=m;i++){
        scanf("%lf%lf%lf",&c.x,&c.y,&du);
        for(int j=0;j<4;j++)
            a[++tot]=c+rotate(zhy[j],du);
    }
    tb(a,tot,b,n);
    double ans=C(b,n);
    ans=ans+2*Pi*r;
    printf("%.2lf\n",ans);
    return 0;
}

原文地址:https://www.cnblogs.com/nianheng/p/10004619.html

时间: 2024-10-16 01:57:50

Luogu-3829 [SHOI2012]信用卡凸包的相关文章

题解 P3829 【[SHOI2012]信用卡凸包】

题目链接 这题如果每个信用卡都不一样不知道怎么做啊--萌新求大佬私信指点迷津qaq Solution [SHOI2012]信用卡凸包 题目大意:给定一个矩形,将其四角替换为\(\frac{1}{4}\)圆弧(也就是信用卡的样子),将这个矩形进行旋转和平移之后得到多个矩形,求凸包长 计算几何 分析:旋转什么的基本操作,我们看比较恶心的圆弧怎么算 样例一可以知道如果\(r=0\)我们直接对矩形顶点求凸包就好,如果\(r\neq0\)我们可以通过平移,将其周长转化为若干个圆心点的凸包周长加一个圆的周长

P3829 [SHOI2012]信用卡凸包

传送门 不难发现这个信用卡凸包的周长就是一个整圆的周长再加上所有的四个边角的点形成的凸包 于是直接把这个凸包求出来即可 还有就是一个向量\((x,y)\)逆时针旋转\(t\)度之后坐标是\((x*cos(t)-y*sin(t),x*sin(t)+y*cos(t))\)(话说原来这玩意儿还有公式的么--) //minamoto #include<bits/stdc++.h> #define inf 1e10 #define eps 1e-10 #define fp(i,a,b) for(regi

SHOI2012 信用卡凸包

题意: 题目链接 题目大意: 给出n个四角为pi/4的圆弧的类矩形,求它们凸包的周长 思路: 乍看似乎没有思路,但注意到r=0时求的是一个裸的凸包 考虑当r不等于0时,我们先按之前的方法求出凸包周长 然后对于每个拐点求其角度,而后求出这段圆弧长,累加即可... for(int i=1;i<=m;++i) { ans+=(q[i]-q[i+1]).dist(); double cs=((q[i]-q[i+1])*(q[i+2]-q[i+1]))/(q[i]-q[i+1]).dist()/(q[i+

bzoj2829 信用卡凸包

2829: 信用卡凸包 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special Judge Submit: 226  Solved: 102 [Submit][Status][Discuss] 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张信用卡的轮廓在上图中

Luogu 2742 二维凸包

Luogu 2742 二维凸包 使用 \(Andrew\) 算法.将点排序后分别求上下凸壳,用单调栈维护. 利用向量叉积来判断当前方向.若 \(v_1\times v_2<0\) ,说明 \(v_2\) 在 \(v_1\) 的右侧, \(<0\) 为左侧, \(=0\) 说明二者共线. 参考讲解. #include<bits/stdc++.h> using namespace std; #define ll long long #define mp make_pair #defin

【计算几何】【凸包】bzoj2829 信用卡凸包

http://hzwer.com/6330.html #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define N 100001 #define EPS 0.00000001 typedef double db; const db PI=acos(-1.0); struct Point{db x,y;}p[N<<2],bao[N<<2]; b

luogu P3291 [SCOI2016]妖怪

二次联通门 : luogu P3291 [SCOI2016]妖怪 /* luogu P3291 [SCOI2016]妖怪 凸包 我果然还是naive 看见这题就想二分 结果惨挂 做了凸包后就想三分 又挂了.. 完美落入了每个坑..果然还是自己太菜 对于每个妖怪,其在(a,b)时的最大战力为过当前点斜率为(-b/a)的直线的截距之和 最大的战力就是最外面的那条直线 对n个点做一个上凸包 最大值一定在凸包的右上部分(自行脑补) 那么这些点的斜率都有着一个范围ki-1<ki<ki+1 那么战力就变为

联赛之前的题表(已完成)汇总(可能有遗漏)

联赛之前的搞搞(其实是懒得分类) 博弈论 poj3537 poj1704 hdu5996两个插头 HDU1693 Eat the Trees COGS1283. [HNOI2004] 邮递员kdtree板子1941: [Sdoi2010]Hide and Seek旋转卡壳 pj2187凸包 cogs896 bzoj2829 信用卡凸包莫比乌斯反演基础 bzoj 4173 zhao gui lv bzoj 3529 mobiwus bzoj 4407 mobiwus bzoj 2818 mobiw

Luogu 4724 三维凸包

Luogu 4724 三维凸包 增量法,维护当前凸包,每次加入一个点 \(P\) ,视其为点光源,将可见面删去,新增由"晨昏线"(分割棱)与 \(P\) 构成的平面. 注意每个平面表面积为其三个端点算出的法向量模长一半. 参考讲解. #include<bits/stdc++.h> using namespace std; #define ll long long #define pii pair<int,int> inline int read() { int