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

计算几何初步(刷蓝书)

时间:2019-10-03 22:14:59      阅读:136      评论:0      收藏:0      [点我收藏+]

标签:cross   intersect   ase   ble   sed   ddl   fine   The   inter   

 

头文件

技术图片
#include<bits/stdc++.h>
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
using namespace std;
typedef long long ll;
const int maxn = 1e3+7;
const double esp = 1e-6;
int dcmp(double x){
    if(fabs(x)<esp)return 0;
    return x<0?-1:1;
}
struct Point{
    double x,y;
    void read(){scanf("%lf%lf",&x,&y);}
    Point(double x = 0,double y = 0):x(x),y(y){}
};
double Cross(const Point A,const Point B){ return A.x*B.y-A.y*B.x; }
double Dot(const Point A,const Point B){ return A.x*B.x+A.y*B.y; }
double Len(const Point A){ return sqrt(Dot(A,A)); }
double Angle(const Point A,const Point B){ return acos(Dot(A,B)/Len(A)/Len(B)); }
Point operator + (const Point A,const Point B){ return Point(A.x+B.x,A.y+B.y); }
Point operator - (const Point A,const Point B){ return Point(A.x-B.x,A.y-B.y); }
Point operator * (const Point A,const double B){ return Point(A.x*B,A.y*B); }
Point operator / (const Point A,const double B){ return Point(A.x/B,A.y/B); }
Point Rotate(const Point A,double rad){return Point(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}
//负数表示顺时针
Point Normal(const Point A){return Point(-A.y/Len(A),A.x/Len(A));}//法向量
bool operator == (const Point A,const Point B){return !dcmp(A.x-B.x)&&!dcmp(A.y-B.y); }
bool operator != (const Point A,const Point B){return !(A == B);}
bool operator < (const Point A,const Point B){return A.x<B.x || (A.x == B.x&&A.y<B.y);}
typedef Point Vector;
struct Circle{
    Point x;
    double r;
    void read(){
        x.read();
        scanf("%lf",&r);
    }
};
bool quickRepel(Point x1,Point y1,Point x2,Point y2){//快速排斥
    Point Lx = Point(min(x1.x,y1.x),min(x1.y,y1.y));
    Point Rx = Point(max(x1.x,y1.x),max(x1.y,y1.y));

    Point Ly = Point(min(x2.x,y2.x),min(x2.y,y2.y));
    Point Ry = Point(max(x2.x,y2.x),max(x2.y,y2.y));

    Point L = Point(max(Lx.x,Ly.x),max(Lx.y,Ly.y));
    Point R = Point(min(Rx.x,Ry.x),min(Rx.y,Ry.y));

    return (L.x<=R.x) && (L.y<=R.y);
}
bool OnSegment(Point P,Point x,Point y){//点在线段上
    if(P == x||P == y)return 1;
    return !dcmp(Cross(x-P,y-P))&&dcmp(Dot(P-x,P-y))<0;
}
bool straddle(Point x1,Point y1,Point x2,Point y2){//跨立实验(线段是否有交点)
    if(!quickRepel(x1,y1,x2,y2))return 0;
    double c1 = Cross(y1-x1,x2-x1),c2 = Cross(y1-x1,y2-x1);
    double c3 = Cross(y2-x2,x1-x2),c4 = Cross(y2-x2,y1-x2);
    return dcmp(c1)*dcmp(c2)<=0 && dcmp(c3)*dcmp(c4)<=0;
    //允许部分重合或在端点重合
    //return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
    //必须只有一个交点且不在端点上
}
Point LinearIntersection(Point P,Vector v,Point Q,Vector w){//解直线交点
    assert(v != w);//Parallel 平行线
    Vector u = P-Q;
    double t = Cross(w,u)/Cross(v,w);
    return P+v*t;
}
Point GetLineProjection(Point P,Point A,Point B){//P投影到AB上的点
    Vector v = B-A;
    return A+v*(Dot(v,P-A)/Dot(v,v));
}
Point SymmetricPoint(Point P,Point A,Point B){//P关于AB的对称点
    return GetLineProjection(P,A,B)*2.0-P;
}
double DistanceToline(Point P,Point A,Point B){//点到直线距离
    Vector v1 = B-A,v2 = P-A;
    return fabs(Cross(v1,v2))/Len(v1);
}
double DistanceToSegment(Point P,Point A,Point B){//点到线段距离
    if(A == B)return Len(P-A);
    Vector v1 = B-A,v2 = P-A,v3 = P-B;
    if(dcmp(Dot(v1,v2))<0)return Len(v2);
    if(dcmp(Dot(v1,v3))>0)return Len(v3);
    return fabs(Cross(v1,v2))/Len(v1);
}
View Code

 

例题:

Morley‘s Theorem

https://vjudge.net/problem/UVA-11178

注意理解三等分角和三等分边不是一个概念

Point GetPoint(Point A,Point B,Point C){
    Vector v1 = C-B;
    double a1 = Angle(A-B,v1);
    v1 = Rotate(v1,a1/3);

    Vector v2 = B-C;
    double a2 = Angle(A-C,v2);
    v2 = Rotate(v2,-a2/3);
    return LinearIntersection(B,v1,C,v2);
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        Point A,B,C;
        A.read(),B.read(),C.read();
        Point D = GetPoint(A,B,C);
        Point E = GetPoint(B,C,A);
        Point F = GetPoint(C,A,B);
        printf("%.6f %.6f ",D.x,D.y);
        printf("%.6f %.6f ",E.x,E.y);
        printf("%.6f %.6f\n",F.x,F.y);
    }
    return 0;
}

 

好看的一笔画LA3263

= = 我没找着这个题

 

狗的距离

https://vjudge.net/problem/UVA-11796

因为没有加速度,所以可以一条狗为参考系,考虑另一条狗的贡献

每次至少跳一个点,所以复杂度也可以保证最多n+m

模拟即可

Point A[maxn],B[maxn];
double Max,Min;
void update(Point P,Point A,Point B){
    Min = min(Min,DistanceToSegment(P,A,B));
    Max = max(Max,Len(P-A));
    Max = max(Max,Len(P-B));
}
int main(){
    int T,n,m,Case = 0;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)A[i].read();
        for(int i=0;i<m;i++)B[i].read();
        double LenA = 0,LenB = 0;
        for(int i=0;i<n-1;i++) LenA += Len(A[i+1]-A[i]);
        for(int i=0;i<m-1;i++) LenB += Len(B[i+1]-B[i]);
        int Sa = 0,Sb = 0;
        Point Pa = A[0],Pb = B[0];
        Min = 1e9,Max = -1e9;
        while(Sa<n-1 && Sb<m-1){
            double La = Len(A[Sa+1]-Pa);
            double Lb = Len(B[Sb+1]-Pb);
            double T = min(La/LenA,Lb/LenB);
            Vector Va = (A[Sa+1]-Pa)/La*T*LenA;
            Vector Vb = (B[Sb+1]-Pb)/Lb*T*LenB;
            update(Pa,Pb,Pb+Vb-Va);
            Pa = Pa+Va;
            Pb = Pb+Vb;
            if(Pa == A[Sa+1])Sa++;
            if(Pb == B[Sb+1])Sb++;
        }
        printf("Case %d: %.0f\n",++Case,Max-Min);
    }
    return 0;
}

 

计算几何初步(刷蓝书)

标签:cross   intersect   ase   ble   sed   ddl   fine   The   inter   

原文地址:https://www.cnblogs.com/revolIA-room/p/11620622.html

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