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


分析
我们发现凸包的圆弧段可以缩成一个圆,然后将直线段向内平移,就可以组成一个多边形
因此对每个卡的四个圆心跑凸包,答案为凸包周长+一个圆的周长
注意四个圆心的计算要用到向量旋转,向量\((x,y)\)逆时针旋转\(\alpha\)(弧度)之后会变成\((x\cos \alpha-y \sin \alpha,x \sin \alpha+y \cos \alpha)\)
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define eps 1e-6
#define maxn 10000
using namespace std;
int n;
const double PI=acos(-1.0);
struct Vector{
double x;
double y;
Vector(){
}
Vector(double _x,double _y){
x=_x;
y=_y;
}
friend Vector operator + (Vector p,Vector q){
return Vector(p.x+q.x,p.y+q.y);
}
friend Vector operator - (Vector p,Vector q){
return Vector(p.x-q.x,p.y-q.y);
}
friend bool operator < (Vector p,Vector q){
if(p.x==q.x) return p.y<q.y;
else return p.x<q.x;
}
};
typedef Vector point;
inline double dot(Vector p,Vector q){
return p.x*q.x+p.y*q.y;
}
inline double dist(point p,point q){
return sqrt(dot(p-q,p-q));
}
inline double cross(Vector p,Vector q){
return p.x*q.y-p.y*q.x;
}
Vector rotate(Vector a,double theta){
return Vector(a.x*cos(theta)-a.y*sin(theta),a.x*sin(theta)+a.y*cos(theta));
}
double a,b,r;
int cnt=0;
point p[maxn*4+5];
int top=0;
point s[maxn*4+5];
int cmp(point x,point y){
double ang=cross(x-p[1],y-p[1]);
if(fabs(ang)<eps) return dist(p[1],x)<dist(p[1],y);
else return ang>eps;
}
int main(){
double x,y,theta;
Vector d[5];
scanf("%d",&n);
scanf("%lf %lf %lf",&a,&b,&r);
a-=2*r;
b-=2*r;
d[1]=Vector(-b/2,a/2);
d[2]=Vector(-b/2,-a/2);
d[3]=Vector(b/2,a/2);
d[4]=Vector(b/2,-a/2);
for(int i=1;i<=n;i++){
scanf("%lf %lf %lf",&x,&y,&theta);
for(int j=1;j<=4;j++){
p[++cnt]=point(x,y)+rotate(d[j],theta);
}
}
#ifdef DEBUG
printf("%d\n",cnt);
for(int i=1;i<=cnt;i++){
printf("(%.2f,%.2f)\n",p[i].x,p[i].y);
}
#endif
for(int i=1;i<=cnt;i++){
if(p[i]<p[1]) swap(p[1],p[i]);
}
sort(p+2,p+1+cnt,cmp);
for(int i=1;i<=cnt;i++){
while(top>1&&cross(s[top]-s[top-1],p[i]-s[top-1])<=eps) top--;
s[++top]=p[i];
}
double ans=0;
for(int i=1;i<top;i++) ans+=dist(s[i],s[i+1]);
ans+=dist(s[top],s[1]);
ans+=2*PI*r;
printf("%.2lf\n",ans);
}
[BZOJ2829] 信用卡 (凸包)的更多相关文章
- BZOJ2829信用卡凸包——凸包
题目描述 输入 输出 样例输入 2 6.0 2.0 0.0 0.0 0.0 0.0 2.0 -2.0 1.5707963268 样例输出 21.66 提示 本样例中的2张信用卡的轮廓在上图中用实线标出 ...
- Bzoj2829 信用卡凸包
Time Limit: 10 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 333 Solved: 155 Description Input ...
- BZOJ-2829 信用卡凸包
凸包题. 我们先把所有信用卡的四个定点的坐标求出来,然后计算凸包长度,最后加上一个圆的周长就行. #include <cstdlib> #include <cstdio> #i ...
- 2019.02.21 bzoj2829: 信用卡凸包(凸包)
传送门 题意:给nnn个A∗BA*BA∗B的矩形,其中每个矩形的四个角被改造成了半径为rrr的四分之一 圆,问这些矩形的凸包周长. 思路:考虑求出圆心的凸包周长然后加上一个整圆的周长,证明很简单,略掉 ...
- 【计算几何】【凸包】bzoj2829 信用卡凸包
http://hzwer.com/6330.html #include<cstdio> #include<cmath> #include<algorithm> us ...
- 【BZOJ2829】[SHOI2012]信用卡凸包(凸包)
[BZOJ2829][SHOI2012]信用卡凸包(凸包) 题面 BZOJ 洛谷 题解 既然圆角的半径都是一样的,而凸包的内角和恰好为\(360°\),所以只需要把圆角的圆心弄下来跑一个凸包,再额外加 ...
- 【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 ...
- bzoj 2829 信用卡凸包(凸包)
2829: 信用卡凸包 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 1342 Solved: 577 [Submit][Status][Disc ...
- [SHOI2012]信用卡凸包(凸包+直觉)
这个题还是比较有趣. 小心发现,大胆猜想,不用证明! 我们发现所谓的信用卡凸包上弧的长度总和就是圆的周长! 然后再加上每个长宽都减去圆的直径之后的长方形的凸包周长即可! #include<ios ...
随机推荐
- Django【第7篇】:Django之ORM跨表操作(聚合查询,分组查询,F和Q查询等)
django之跨表查询及添加记录 一:创建表 书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many); ...
- vertica merge 优化
-- 查看RDS的订单数(MySQL) select count(*) from ( SELECT tid, IF(LOCATE('pay_time', jdp_response)=0 ...
- M(model)V(view)C(controller,serlvet),(分) 静态工厂模式,单例模式
- (16)Python3.5+Pyqt5+PyCharm+Opencv3.3+Qtdesigner开发环境配置
一:Python3.3和Pyqt5的安装 注意:两个的版本一定要对应,一定要对应,一定要对应,重要的事情说三遍. 因为我自己的电脑是64位的,所以我下载的都是64位版本的,且都是3.5版本的:这两个一 ...
- Linux用户和用户组指令
1.创建用户 >useradd username 创建用户 >passwd username 给用户设置密码 ======================================= ...
- Beauty Values
Beauty Values 题意:给$n$个数, 定义它的Beauty Values为所有连续子区间的(区间长度*区间内不同数字的数目)求和 求Beauty Values A[i]数组表示数字i最近一 ...
- [ethereum源码分析](5) 创建新账号
前言 在上一章我们介绍了 ethereum运行开启console 的过程,那么在这一章我们将会介绍如何在以太坊中创建一个新的账号.以下的理解可能存在错误,如果各位大虾发现错误,还望指正. 指令分析 指 ...
- [ethereum源码分析](4) ethereum运行开启console
前言 在上一章我们介绍了 ethereum初始化指令 ,包括了系统是如何调用指令和指令的执行.在本章节我们将会介绍 geth --datadir dev/data/ --networkid cons ...
- Python学习笔记(三)- SyntaxError: Non-ASCII character '\xe7' in file
在编辑Python时,当有中文输出或者注释时,出现错误提示:“SyntaxError: Non-ASCII character '\xe7' in file“ 原因:python的默认编码文件是用的A ...
- HTTP入门(二):用Chrome开发者工具查看 HTTP 请求与响应
HTTP入门(二):用Chrome开发者工具查看 HTTP 请求与响应 本文简单总结HTTP的请求与响应. 本文主要目的是对学习内容进行总结以及方便日后查阅. 详细教程和原理可以参考HTTP文档(MD ...