CF几何刷题记录

不开坑就没有方向……
(虽然开了坑也会跑路……)
想把CF里过题人数100+的几何题都做一做……
那就先从1000-往下做吧

模板:

#include<bits/stdc++.h>
#define ERROR 1e99
#define N 100005
using namespace std;
typedef double data;
typedef long long LL;
const data PI=acos(-1.);
const data EPS=1E-10;
int Zero(data O){return fabs(O)<=EPS;}
void Read(data &now){double IO;scanf("%lf",&IO);now=IO;}
struct Point{
    data x,y;
    void read(){Read(x);Read(y);}
    void Print(){printf("%lf %lf\n",(double)x,(double)y);}
    void init(data _x,data _y){x=_x;y=_y;}
    data operator * (const Point &b)const{
        return x*b.y-y*b.x;
    }
    Point operator * (const data &b)const{
        return (Point){x*b,y*b};
    }
    data operator ^ (const Point &b)const{
        return x*b.x+y*b.y;
    }
    Point operator - (const Point &b)const{
        return (Point){x-b.x,y-b.y};
    }
    Point operator + (const Point &b)const{
        return (Point){x+b.x,y+b.y};
    }
    int operator < (const Point &b)const{
        return x<b.x||x==b.x&&y<b.y;
    }
    int operator == (const Point &b)const{
        return Zero(x-b.x)&&Zero(y-b.y);
    }
    void Rotate(data alpha){
        data _x=x*cos(alpha)-y*sin(alpha);
        data _y=y*cos(alpha)+x*sin(alpha);
        x=_x;y=_y;
    }
}ERRORPOINT=(Point){ERROR,ERROR};
struct Line{
    Point p,q;
};
struct Circle{
    Point O;data r;
    void read(){O.read();Read(r);}
};
data sqr(data x){return x*x;}
data dist(Point A,Point B){return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));}
int Intersection(Line A,Line B,Point &ret){
    ret=A.p;
    data u=(A.p-B.p)*(B.p-B.q);
    data v=(A.p.x-A.q.x)*(B.p.y-B.q.y)-(A.p.y-A.q.y)*(B.p.x-B.q.x);
    if (Zero(v)) return 0;u/=v;
    ret.x+=(A.q.x-A.p.x)*u;
    ret.y+=(A.q.y-A.p.y)*u;
    return 1;
}
int Intersection(Circle C,Line L,Point &A,Point &B){
    Point p=C.O;p.x+=L.p.y-L.q.y;p.y+=L.q.x-L.p.x;
    Intersection((Line){p,C.O},L,p);
    data tmp=sqr(C.r)-sqr(p.x-C.O.x)-sqr(p.y-C.O.y);
    if (tmp<-EPS) return 0;
    data t=sqrt(max(tmp,0.))/dist(L.p,L.q);
    A=p+(L.q-L.p)*t;B=p-(L.q-L.p)*t;
    return 1;
}
int Intersection(Circle C1,Circle C2,Point &A, Point &B) {
    double d = dist(C1.O,C2.O);
    if (d<fabs(C1.r-C2.r)-EPS || d>fabs(C1.r+C2.r)+EPS) return 0;
    double cosa = (sqr(C1.r) + sqr(d) - sqr(C2.r)) / (2 * C1.r * d);
    double sina = sqrt(max(0., 1. - sqr(cosa)));
    A = B = C1.O;
    A.x += C1.r / d * ((C2.O.x - C1.O.x) * cosa + (C2.O.y - C1.O.y) * -sina);
    A.y += C1.r / d * ((C2.O.x - C1.O.x) * sina + (C2.O.y - C1.O.y) * cosa);
    B.x += C1.r / d * ((C2.O.x - C1.O.x) * cosa + (C2.O.y - C1.O.y) * sina);
    B.y += C1.r / d * ((C2.O.x - C1.O.x) *-sina + (C2.O.y - C1.O.y) * cosa);
    return 1;
}

//此处默认data是int 
int Polar_cmp(const Point &A,const Point &B){
    if (A.y==0&&B.y==0) return A.x>0&&B.x<0;
    if (A.y==0) return A.x>0||B.y<0;
    if (B.y==0) return B.x<0&&A.y>0;
    if ((A.y>0)^(B.y>0)) return A.y>0;
    return (A*B)>0;
}

vector<Point>Make_Convex(vector<Point>now){
    sort(now.begin(),now.end());
    if (now.size()<3) return now;
    for (int i=0;i<now.size();i++)
        now[i].Print();
    puts("");
    
    vector<Point>up;up.clear();
    up.push_back(now[0]);
    for (int i=1;i<now.size();i++){
        for (;up.size()>1&&(up[up.size()-2]-up.back())*(now[i]-up.back())<=0;up.pop_back());
        up.push_back(now[i]);
    }
    vector<Point>down;down.clear();
    down.push_back(now.back());
    for (int i=now.size()-1;i>=0;i--){
        for (;down.size()>1&&(down[down.size()-2]-down.back())*(now[i]-down.back())<=0;down.pop_back());
        down.push_back(now[i]);
    }
    
    vector<Point>ret;ret.clear();
    for (int i=down.size()-1;i>0;i--)
        ret.push_back(down[i]);
    for (int i=up.size()-1;i>0;i--)
        ret.push_back(up[i]);
    return ret;
}

//以下是最小圆覆盖

//两个点 
Circle make_2(Point p,Point q){
    Circle ret;
    ret.O.x=(p.x+q.x)/2.0;
    ret.O.y=(p.y+q.y)/2.0;
    ret.r=dist(ret.O,p);
    return ret;
}
//返回三角形的外心  
Circle make_3(const Point &a,const Point &b,const Point &c)  {
    data a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)/2;  
    data a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)/2;  
    data d=a1*b2-a2*b1;
    Circle ret;
    ret.O.x=a.x+(c1*b2-c2*b1)/d;
    ret.O.y=a.y+(a1*c2-a2*c1)/d;
    ret.r=dist(ret.O,a);
    return ret;
} 
bool IN(Circle now,Point a){
    return (dist(now.O,a)<=now.r+EPS);
}
Circle Smallest_Circle(Point *a,int n){
    if (n==1) return (Circle){a[1],0};
    srand(2333);
    random_shuffle(a+1,a+n+1);
    Circle cur=make_2(a[1],a[2]);
    for (int i=2;i<=n;i++)
        if (!IN(cur,a[i])){
            cur=make_2(a[1],a[i]);
            for (int j=1;j<i;j++)
                if (!IN(cur,a[j])){
                    cur=make_2(a[i],a[j]);
                    for (int k=1;k<j;k++)
                        if (!IN(cur,a[k]))
                            cur=make_3(a[i],a[j],a[k]);
                }
        }
    return cur;
}
int main(){
}

【280A】
   有一个水平放置的长方形。求它绕中心旋转\(\alpha\)度后的图形与原图形的面积交。
   直接分类讨论感觉很烦烦。本来想趁机搞一个HPI的板子,可是放弃了……
   后来用了一个比较巧妙的做法。把两个矩形的边框拿来交一交,只有都在两条直线内的交点才会是最终答案凸包上的点。然后随便做个凸包就好了。

【793C】
   有一坨给定初始坐标和方向向量的点,还有一个固定的矩形。问一个最早的时刻,使得所有点都严格在矩形内部。
   因为是矩形,把直线画出来后,最多只会与矩形交两个unique的点(注意到<2必然是无解)。然后算一算对应时间求个交即可。
   此题最大的坑点是“严格”。最后的合法区间如果只有一个值,那么其实是不合法的;这个eps就很耐人寻味。还要注意那些和边框重合的运动路线也是不合法的。

【166B】
   分析一下题目性质,转化为问一个点是否严格在一个凸包内部。
   分别维护出上凸壳和下凸壳,每次二分后用叉积判断即可。

【600D】
   求两个圆面积交……看起来很old,确是一道特别帅气的题……
   其实就是求两个弓形的面积。我本来是直接求交点,用叉积计算三角形面积,然后余弦定理算一下扇形的角度。
   但是数据范围太大了,求交的精度会爆炸……
   其实知道了半径和距离后,换个三角形研究,即可算出扇形的角度……然后根据角度再计算三角形。
   仔细想想,这也能开发出求交的另一个方法。虽然有三角函数,但感觉精度靠谱很多。

【2C】
   对于其中两个圆,可以发现符合要求的点在一条直线或者一个圆上。
   那么最终答案就在圆/直线与圆/直线的交点上。检验板子的好题……

转载于:https://www.cnblogs.com/jiangshibiao/p/8456297.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值