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(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
using namespace std;
const int N=1e5+5;const double Pi=acos(-1.0);
struct node{
    double x,y;
    node(double X=0,double Y=0):x(X),y(Y){}
    inline node operator +(const node &b)const
    {return node(x+b.x,y+b.y);}
}p[N],st[N],rs;
int n,k,top,tot;double ans,a,b,r,x,y,t;
inline bool cmp(node a,node b){
    double A=atan2(a.y-p[1].y,a.x-p[1].x);
    double B=atan2(b.y-p[1].y,b.x-p[1].x);
    return A!=B?A<B:a.x<b.x;
}
inline double cross(node a,node b,node c){return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);}
inline double dis(node a,node b){return sqrt((b.y-a.y)*(b.y-a.y)+(b.x-a.x)*(b.x-a.x));}
inline node rotate(node a,double t){
    double s=sin(t),c=cos(t);
    return node(a.x*c-a.y*s,a.x*s+a.y*c);
}
int main(){
//  freopen("testdata.in","r",stdin);
    scanf("%d%lf%lf%lf",&n,&b,&a,&r),p[0]=node(inf,inf);
    a/=2.0,b/=2.0;
    fp(i,1,n){
        scanf("%lf%lf%lf",&x,&y,&t),rs=node(x,y);
        p[++tot]=rotate(node(a-r,b-r),t)+rs;
        p[++tot]=rotate(node(r-a,b-r),t)+rs;
        p[++tot]=rotate(node(a-r,r-b),t)+rs;
        p[++tot]=rotate(node(r-a,r-b),t)+rs;
    }
    fp(i,1,tot)if(p[0].y>p[i].y||(p[0].y==p[i].y&&p[0].x>p[i].x))p[0]=p[i],k=i;
    swap(p[k],p[1]),sort(p+2,p+1+tot,cmp);
    st[0]=p[1],st[1]=p[2],top=1;
    fp(i,3,tot){
        while(top&&cross(st[top-1],p[i],st[top])>=0)--top;
        st[++top]=p[i];
    }
    ans=2*Pi*r,st[++top]=st[0];
    fp(i,1,top)ans+=dis(st[i],st[i-1]);
    printf("%.2lf\n",ans);return 0;
}

原文地址:https://www.cnblogs.com/bztMinamoto/p/10000517.html

时间: 2024-10-11 03:51:58

P3829 [SHOI2012]信用卡凸包的相关文章

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

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

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.141592653589793

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张信用卡的轮廓在上图中

【计算几何】【凸包】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

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

联赛之前的搞搞(其实是懒得分类) 博弈论 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

POJ3528 HDU3662 三维凸包模板

POJ3528 HDU3662 第一道题 给定若干点 求凸包的表面积,第二题 给定若干点就凸包的面数. 简单说一下三维凸包的求法,首先对于4个点假设不共面,确定了唯一四面体,对于一个新的点,若它不在四面体内,为了让它进入凸包, 则对于所有凸包上的边,若边的一面是该点可以看到的而另一面看不到,则该点与该边构成的面要加入凸包. 模板代码非常清晰, #include<stdio.h> #include<algorithm> #include<string.h> #includ

关于2016.12.12——T1的反思:凸包的意义与应用

2016.12.12 T1 给n个圆,保证圆圆相离,求将圆围起来的最小周长.n<=100 就像上图.考场上,我就想用切线的角度来做凸包.以圆心x,y排序,像点凸包一样,不过用两圆之间的下切线角度来判断. 这就是下切线(我自己瞎编的名字): 好像是对的啊: 然后我就保证必AC的希望,用这种写法交了,然后就只得了N=2的暴力分... 自以为是正解,却落得如此下场... 为什么?这样不对吗?借用学长的力量,果然被Hack掉了: 这种情况,圆心排序后,检测的顺序并不是圆上的切点的顺序,自然就会挂. 蓝瘦

信用卡利息计算

 ● 假设张先生的帐单日为每月5日,到期还款日为每月23日; ● 4月5日银行为张先生打印的本期帐单包括了他从3月5日至4月5日之间的所有交易帐务; ● 本月帐单周期张先生仅有一笔消费--3月30日,消费金额为人民币1000元; ● 张先生的本期帐单列印"本期应还金额"为人民币1000元,"最低还款额"为100元; ● 不同的还款情况下,张先生的循环利息分别为: (1) 若张先生于4月23日前,全额还款1000元,则在5月5日的对帐单中循环利息= 0元. (2) 若