思路

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

然后就好做了

注意平行时把距离小的排在前面,栈中至少要有1个元素(top>1),凸包中如果存在叉积为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;
}

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

  1. luogu P3829 [SHOI2012]信用卡凸包 凸包 点的旋转

    LINK:信用卡凸包 当 R==0的时候显然是一个点的旋转 之后再求凸包即可. 这里先说点如何旋转 如果是根据原点旋转的话 经过一个繁杂的推导可以得到一个矩阵. [cosw,-sinw] [sinw, ...

  2. [洛谷P3829][SHOI2012]信用卡凸包

    题目大意:有$n$张一模一样的信用卡,每个角进行了圆滑处理,问这些卡组成的“凸包”的周长 题解:发现是圆滑处理的圆心围成的凸包加上一个圆周即可 卡点:输入长宽弄反,然后以为是卡精 C++ Code: ...

  3. 【BZOJ2829】[SHOI2012]信用卡凸包(凸包)

    [BZOJ2829][SHOI2012]信用卡凸包(凸包) 题面 BZOJ 洛谷 题解 既然圆角的半径都是一样的,而凸包的内角和恰好为\(360°\),所以只需要把圆角的圆心弄下来跑一个凸包,再额外加 ...

  4. [SHOI2012]信用卡凸包(凸包+直觉)

    这个题还是比较有趣. 小心发现,大胆猜想,不用证明! 我们发现所谓的信用卡凸包上弧的长度总和就是圆的周长! 然后再加上每个长宽都减去圆的直径之后的长方形的凸包周长即可! #include<ios ...

  5. Luogu-3829 [SHOI2012]信用卡凸包

    这道题的转化很巧妙,可以把信用卡四个角的圆心看做平面上的点来做凸包,\(ans\)就是凸包周长加上一个圆的周长 // luogu-judger-enable-o2 #include<cmath& ...

  6. [SHOI2012]信用卡凸包(计算几何)

    /* 考验观察法?? 可以发现最终答案等于所有作为圆心的点求出凸包的周长加上一个圆的周长 向量旋转 (x1, y1) 相较于 (x2, y2) 旋转角c 答案是 (dtx * cosc - dty * ...

  7. 【BZOJ 2829】 2829: 信用卡凸包 (凸包)

    2829: 信用卡凸包 Description Input Output Sample Input 2 6.0 2.0 0.0 0.0 0.0 0.0 2.0 -2.0 1.5707963268 Sa ...

  8. bzoj 2829 信用卡凸包(凸包)

    2829: 信用卡凸包 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1342  Solved: 577 [Submit][Status][Disc ...

  9. [BZOJ2829] 信用卡 (凸包)

    [BZOJ2829] 信用卡 (凸包) 题面 信用卡是一个矩形,唯四个角做了圆滑处理,使他们都是与矩形两边相切的1/4园,如下图所示,现在平面上有一些规格相同的信用卡,试求其凸包的周长.注意凸包未必是 ...

随机推荐

  1. NYOJ - 矩形嵌套(经典dp)

    矩形嵌套时间限制:3000 ms | 内存限制:65535 KB 描述 有n个矩形,每个矩形可以用a,b来描述,表示长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b< ...

  2. MySQL数据库报错pymysql.err.InterfaceError: (0, '')

    今天入库的时候出现了报错pymysql.err.InterfaceError: (0, ''),经过排查,发现是由于把连接数据库的代码放到了插入函数的外部,导致多线程运行出错 def write_in ...

  3. iTextSharpH

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. sql中join与left-join图解区别

      select a.* from YG_BRSYK a left join(SELECT DISTINCT SYXH, STUFF((SELECT '.'+MS FROM #lsb where SY ...

  5. ubuntu linux修改文件所属用户(owner属主)和组(groud属组、用户组)

    使用chown命令可以修改文件或目录所属的用户: 命令格式:sudo chown 用户 目录或文件名 例如:sudo chown -R griduser /home/dir1  (把home目录下的d ...

  6. 范进中Nature——儒林外史新义

    范进中Nature——儒林外史新义 范进发了文章回办公室,实验室一块儿搬砖的挂名作者俱各欢喜.正待烧锅煮方便面,只见他老板胡副教授,手里拿着一包外卖和一瓶红星二锅头,走了进来.范进向他作揖,坐下.胡副 ...

  7. Luogu4451 [国家集训队]整数的lqp拆分

    题目链接:洛谷 题目大意:求对于所有$n$的拆分$a_i$,使得$\sum_{i=1}^ma_i=n$,$\prod_{i=1}^mf_{a_i}$之和.其中$f_i$为斐波那契数列的第$i$项. 数 ...

  8. Git环境配置

    1,下载Git-2.16.2-64-bit.exe并安装, 全部为默认设置 下载地址:http://git-scm.com/download/win 2 在开始菜单中,单击Git CMD,执行下面命令 ...

  9. 九、使用多线程——NSThread,GCD和NSOperation

    概述 早上起床,你先打开洗衣机,然后用热水把泡面泡上,接着打开电脑开启一天的码农生活.其中“洗衣服”.“泡泡面”和“码代码”3个任务(线程)同时进行,这就是多线程.网上有许多关于多线程的经典解释,此处 ...

  10. CSS样式中文字的换行

    在我们做输出时可能会遇到这样一个问题,就是汉字和英文字母相遇,然后自动换行的问题.例如,当我在输出产品标题时,由于产品名称比较长,包括汉字和英文字母,FF下浏览是正常的,而IE下面 英文会出现换行.当 ...