[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 ...
随机推荐
- 安装后jdk1.8 配置环境变量以后 版本显示还是1.7
配置图如下 1.7版本不用卸载 不用就可以了
- man da'te
DATE(1) 用户命令 DATE(1) 名称 日期-打印或设置系统日期和时间 简介 date [OPTION]... ...
- appium环境666
一.安装JDK,配置JDK环境 appium下载地址: https://github.com/appium/appium-desktop/releases/ 百度搜索下载就行,这里分享一个下载链 ...
- linux运维、架构之路-tomcat服务
一.tomcat介绍 Tomcat服务器是一个免费的开放源代码的Web应用服务器,即能处理静态页面,又能处理动态的java页面 二.JDK安装 jdk是java开发工具包,也可以叫java ...
- 51Nod 1277 字符串中的最大值 ( KMP && DP )
题意 : 一个字符串的前缀是指包含该字符第一个字母的连续子串,例如:abcd的所有前缀为a, ab, abc, abcd.给出一个字符串S,求其所有前缀中,字符长度与出现次数的乘积的最大值.例如:S ...
- CodeForces 1197D Yet Another Subarray Problem
Time limit 2000 ms Memory limit 262144 kB Source Educational Codeforces Round 69 (Rated for Div. 2) ...
- ACM 求全排列(字典序、邻位对换、递增进位制数,递减进位制数)
字典序:(联合康托展开就也可以按照中介数求) 邻位对换.递增进位制数,递减进位制数:具体的实现和算法讲解如下: 代码..C++版的实现并不好..因为是挨个向后找的,如果K很大的时候会超时,不过...思 ...
- 爬虫小例1:ajax形式的网页数据的抓取
---恢复内容开始--- 下面记录如何抓取ajax形式加载的网页数据: 目标:获取“https://movie.douban.com/typerank?type_name=%E5%89%A7%E6%8 ...
- SQL GROUP BY两个列
首先group by 的简单说明: group by 一般和聚合函数一起使用才有意义,比如 count sum avg等,使用group by的两个要素: (1) 出现在select后面的字段 要 ...
- ORA-00972
SQL> select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') as 日期时间 from dual;select to_char(sysdate,'YY ...