这题如果每个信用卡都不一样不知道怎么做啊……萌新求大佬私信指点迷津qaq
Solution [SHOI2012]信用卡凸包
题目大意:给定一个矩形,将其四角替换为\(\frac{1}{4}\)圆弧(也就是信用卡的样子),将这个矩形进行旋转和平移之后得到多个矩形,求凸包长
计算几何
分析:旋转什么的基本操作,我们看比较恶心的圆弧怎么算
样例一可以知道如果\(r=0\)我们直接对矩形顶点求凸包就好,如果\(r\neq0\)我们可以通过平移,将其周长转化为若干个圆心点的凸包周长加一个圆的周长
这个操作可以理解为将凸包整体向内收缩了\(r\),所以不影响正确性,然后我们直接求一个朴素凸包周长最后加上一个半径为\(r\)的圆周长即可
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 5e4 + 100;
const double pi = acos(-1),eps = 1e-4;
struct Point{
double x,y;
}p[maxn],stk[maxn],w[4],org;
typedef Point Vector;
inline Vector operator + (Vector a,Vector b){return Vector{a.x + b.x,a.y + b.y};}
inline Vector operator - (Vector a,Vector b){return Vector{a.x - b.x,a.y - b.y};}
inline Vector rotate(Vector now,double theta){return Vector{now.x * cos(theta) - now.y * sin(theta),now.x * sin(theta) + now.y * cos(theta)};}
inline double cross(Vector a,Vector b){return a.x * b.y - a.y * b.x;}
inline double sq(double x){return x * x;}
inline double dis(Point a,Point b){return sqrt(sq(a.x - b.x) + sq(a.y - b.y));}
inline int dcmp(double x){return fabs(x) < eps ? 0 : (x < 0 ? -1 : 1);}
inline bool operator < (Point a,Point b){
double tmp = cross(a - org,b - org);
if(dcmp(tmp) > 0)return true;
else if(dcmp(tmp) == 0 && dis(org,a) < dis(org,b))return true;
else return false;
}
istream& operator >> (istream &in,Point &x){
in >> x.x >> x.y;
return in;
}
ostream& operator << (ostream &out,Point &x){
out << x.x << " " << x.y;
return out;
}
int n,tot,top;
double a,b,r,ans;
int main(){
ios::sync_with_stdio(false);
cout << setiosflags(ios::fixed) << setprecision(2);
cin >> n;
cin >> a >> b >> r;
w[0] = Vector{-0.5 * b + r,0.5 * a - r};
w[1] = Vector{0.5 * b - r,0.5 * a - r};
w[2] = Vector{0.5 * b - r,-0.5 * a + r};
w[3] = Vector{-0.5 * b + r,-0.5 * a + r};
for(int i = 1;i <= n;i++){
Point from;double theta;
cin >> from >> theta;
for(int i = 0;i < 4;i++)
p[++tot] = from + rotate(w[i],theta);
}
org = p[1];
for(int i = 1;i <= tot;i++)
if(p[i].y < org.y || (p[i].y == org.y && p[i].x < org.x))org = p[i];
sort(p + 1,p + 1 + tot);
stk[++top] = p[1];
for(int i = 2;i <= tot;i++){
while(top > 1 && dcmp(cross(stk[top - 1] - stk[top],p[i] - stk[top])) >= 0)top--;
stk[++top] = p[i];
}
stk[top + 1] = p[1];
for(int i = 1;i <= top;i++)ans += dis(stk[i],stk[i + 1]);
ans += pi * 2 * r;
cout << ans << '\n';
return 0;
}
原文地址:https://www.cnblogs.com/colazcy/p/12064538.html
时间: 2024-10-12 15:59:23