码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-12-18 23:37:20      阅读:123      评论:0      收藏:0      [点我收藏+]

标签:转化   str   理解   pac   rom   tps   man   eps   poi   

题目链接

这题如果每个信用卡都不一样不知道怎么做啊……萌新求大佬私信指点迷津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;
}

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

标签:转化   str   理解   pac   rom   tps   man   eps   poi   

原文地址:https://www.cnblogs.com/colazcy/p/12064538.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!