• 基础计算几何


    计算几何把几个模板写好,然后根据不同题目分析即可。

    必要代码:

    const double eps=1e-8;
    const double PI=acos(-1.0);
    typedef double lf;
    int sgn(double x)
    {
        if(fabs(x)<eps) return 0;
        if(x<0) return -1;
        else return 1;
    }
    View Code

    二维平面上的点:

    struct vec{
        lf x,y;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
        lf operator ^(const vec &b){return x*b.y-y*b.x;}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    }q[maxn],pp;
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    View Code

    判断两条线段是否相交

    bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd
        #define SJ(x) max(a.x,b.x)<min(c.x,d.x)
        || max(c.x,d.x)<min(a.x,b.x)
        if(SJ(x) || SJ(y))return 0;
        #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0
        return SJ2(a,b,c,d) && SJ2(c,d,a,b);
    }
    View Code

    判断线段与直线是否相交

    bool judge(vec a,vec b,vec c,vec d)
    { 
        return sgn(cross(d,a,b))*sgn(cross(c,a,b))<=0;
    }
    View Code

    POJ - 2318

    二分+叉积寻找位置即可

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    //#include<chrono>
    #include<vector>
    #include<list>
    #include<queue>
    #include<string>
    #include<set>
    #include<map>
    //#include<unordered_set>
    //#include<unordered_map>
    #define debug frelimiten("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    using namespace std;
    typedef long long ll;
    typedef double lf;
    typedef pair<int, int> pii;
    const int maxn = 10500+10;
    const int INF = 0x3f3f3f3f; 
    const int mod = 998244353;
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    struct vec{
        lf x,y;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    }a[maxn],pp;
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    int vis[maxn],n,m,i,x1,y1,x2,y2,x,y,u,l;
    int main()
    {
        while (~scanf("%d",&n))
        {
            if (n==0) break;
            //scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
            memset(vis,0,sizeof(vis));
            m=read(),x1=read(),y1=read(),x2=read(),y2=read();
            for (i=0;i<n;i++)
            {
                scanf("%d%d",&u,&l);
                a[i]=vec(u,y1);
                a[i+n+1]=vec(l,y2);
            }
            a[n]=vec(x2,y1),a[2*n+1]=vec(x2,y2);
            for (i=1;i<=m;i++)
            {
                x=read(),y=read();
                pp=vec(x,y);
                int ll=0,rr=n;
                int tmp=0;
                while (ll<=rr)
                {
                    int mid=(ll+rr)>>1;
                    if (cross(pp,a[mid],a[mid+n+1])<0)
                    {
                        rr=mid-1;
                        tmp=mid;
                    }
                    else ll=mid+1;
                }
                vis[tmp]++;
                //vis[rr]++;
            }
            for (i=0;i<=n;i++)
            {
                cout<<i<<": "<<vis[i]<<endl;
            }
            cout<<endl;
        }
        return 0;
    }
    View Code

    POJ - 2398

    与上一题相同,只需多个排序

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    //#include<chrono>
    #include<vector>
    #include<list>
    #include<queue>
    #include<string>
    #include<set>
    #include<map>
    //#include<unordered_set>
    //#include<unordered_map>
    #define debug frelimiten("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    using namespace std;
    typedef long long ll;
    typedef double lf;
    typedef pair<int, int> pii;
    const int maxn = 10500+10;
    const int INF = 0x3f3f3f3f; 
    const int mod = 998244353;
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    struct vec{
        lf x,y;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    }pp;
    struct node
    {
        vec s,t;
    }a[maxn];
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const node &a,const node &b){return make_pair(a.s.x,a.s.y)<make_pair(b.s.x,b.s.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    int vis[maxn],ans[maxn],n,m,i,x1,y1,x2,y2,x,y,u,l;
    int main()
    {
        while (~scanf("%d",&n))
        {
            if (n==0) break;
            //scanf("%d%d%d%d%d",&m,&x1,&y1,&x2,&y2);
            memset(vis,0,sizeof(vis));
            memset(ans,0,sizeof(ans));
            m=read(),x1=read(),y1=read(),x2=read(),y2=read();
            for (i=0;i<n;i++)
            {
                scanf("%d%d",&u,&l);
                a[i].s=vec(u,y1);
                a[i].t=vec(l,y2);
            }
            a[n].s=vec(x2,y1),a[n].t=vec(x2,y2);
            sort(a,a+n+1,cmp_xy);
            for (i=1;i<=m;i++)
            {
                x=read(),y=read();
                pp=vec(x,y);
                int ll=0,rr=n;
                int tmp=0;
                while (ll<=rr)
                {
                    int mid=(ll+rr)>>1;
                    if (cross(pp,a[mid].s,a[mid].t)<0)
                    {
                        rr=mid-1;
                        tmp=mid;
                    }
                    else ll=mid+1;
                }
                vis[tmp]++;
            }
            
            for (i=0;i<=n;i++) 
            {
                if (vis[i]>0) ans[vis[i]]++;
            }
            cout<<"Box"<<endl;
            for (i=1;i<=n;i++)
            {
                if (ans[i]>0)
                    cout<<i<<": "<<ans[i]<<endl;
            }
        }
        return 0;
    }
    View Code

    ※POJ - 3304

    看了证明才懂这题的思路:

    1:把问题转化为是否存在一条直线与每条线段都有交点。证明:若存在一条直线l和所有线段相交,作一条直线m和l垂直,则m就是题中要求的直线,所有线段投影的一个公共点即为垂足。

    2:枚举两两线段的各一个端点,连一条直线,再判断剩下的线段是否都和这条直线有交点。证明:若有l和所有线段相交,则可保持l和所有线段相交,左右平移l到和某一线段交于端点停止(“移不动了”)。然后绕这个交点旋转。也是转到“转不动了”(和另一线段交于其一个端点)为止。这样就找到了一个新的l满足题意,而且经过其中两线段的端点。

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    //#include<chrono>
    #include<vector>
    #include<list>
    #include<queue>
    #include<string>
    #include<set>
    #include<map>
    //#include<unordered_set>
    //#include<unordered_map>
    #define debug frelimiten("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    using namespace std;
    typedef long long ll;
    typedef double lf;
    typedef pair<int, int> pii;
    const int maxn = 10500+10;
    const int INF = 0x3f3f3f3f; 
    const int mod = 998244353;
    const double eps=1e-8;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    int sgn(double x)
    {
        if(fabs(x)<eps) return 0;
        if(x<0) return -1;
        else return 1;
    }
    struct vec{
        lf x,y;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
    //    lf operator *(const vec &b){return x*b.x + y*b.y;}
        lf operator ^(const vec &b){return x*b.y-y*b.x;}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    };
    struct Line
    {
        vec s,t;
    }a[maxn];
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const Line &a,const Line &b){return make_pair(a.s.x,a.s.y)<make_pair(b.s.x,b.s.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    //double xmult(vec p0,vec p1,vec p2) 
    //{
    //    return (p1-p0)^(p2-p0);
    //}
    double dist(vec a,vec b)
    {
        return sqrt(dot(b-a,b-a));
    }
    bool judge(vec a,vec b,vec c,vec d){ 
        return sgn(cross(d,a,b))*sgn(cross(c,a,b))<=0;
    }
    bool flag;
    int t,i,n,j;
    double xx,yy;
    bool check(vec x,vec y,int n)
    {
        if (sgn(dist(x,y)==0)) return false;
            for (ri k=1;k<=n;k++)
                if (!judge(x,y,a[k].s,a[k].t)) return false;
        return true;
    }
    int main()
    {
        t=read();
        while (t--)
        {
            n=read();
            for (i=1;i<=n;i++)
            {
                scanf("%lf%lf",&xx,&yy);
                a[i].s=vec(xx,yy);
                scanf("%lf%lf",&xx,&yy);
                a[i].t=vec(xx,yy);
            }
            flag=false;
            for (i=1;i<=n&&!flag;i++)
                for (j=1;j<=n&&!flag;j++)
                {
                    if (check(a[i].s,a[j].t,n) || check(a[i].s,a[j].s,n) || check(a[i].t,a[j].t,n) || check(a[i].t,a[j].s,n))
                    {
                        flag=true;
                        break;
                    }
                }
            if (flag) printf("Yes!
    ");
                else printf("No!
    ");
        }
        return 0;
    }
    View Code

    POJ - 1556

    首先肯定要贴着点走,这时只需一个个离散每个点的位置,求一遍最短路即可。

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    //#include<chrono>
    #include<vector>
    #include<list>
    #include<queue>
    #include<string>
    #include<set>
    #include<map>
    //#include<unordered_set>
    //#include<unordered_map>
    #define debug frelimiten("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    using namespace std;
    typedef long long ll;
    typedef double lf;
    typedef pair<int, int> pii;
    const int maxn = 10500+10;
    const int INF = 0x3f3f3f3f; 
    const int mod = 998244353;
    const double eps=1e-8;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    int sgn(double x)
    {
        if(fabs(x)<eps) return 0;
        if(x<0) return -1;
        else return 1;
    }
    struct vec{
        lf x,y;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
        lf operator ^(const vec &b){return x*b.y-y-b.x;}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    }b[maxn];
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    double dist(vec a,vec b)
    {
        return sqrt(dot((a-b),(a-b)));
    }
    bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd
        #define SJ(x) max(a.x,b.x)<min(c.x,d.x)
        || max(c.x,d.x)<min(a.x,b.x)
        if(SJ(x) || SJ(y))return 0;
        #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0
        return SJ2(a,b,c,d) && SJ2(c,d,a,b);
    }
    int n,i,j,k;
    double x,y1,y2,y3,y4,dis[505][505];
    bool flag;
    int main()
    {
        while (~scanf("%d",&n))    
        {
            if (n==-1) break;
            b[0]=vec(0,5);
            for (i=0;i<n;i++)
            {
                scanf("%lf",&x);
                scanf("%lf%lf%lf%lf",&y1,&y2,&y3,&y4);
                b[i*4+1]=vec(x,y1);
                b[i*4+2]=vec(x,y2);
                b[i*4+3]=vec(x,y3);
                b[i*4+4]=vec(x,y4);
            }
            b[n*4+1]=vec(10,5);
            memset(dis,0,sizeof(dis));
            for (i=0;i<=4*n+1;i++)
                for (j=i+1;j<=4*n+1;j++) 
                {
                    int xx=(i-1)/4;
                    int yy=(j-1)/4;
                    if (i==0) xx=-1;
                    flag=true;
                    for (k=xx+1;k<yy;k++)
                    {
                        if (judge(b[4*k+1],vec(b[4*k+1].x,0),b[i],b[j]))
                        {
                            flag=false;
                            break;
                        }
                        if (judge(b[4*k+2],b[4*k+3],b[i],b[j]))
                        {
                            flag=false;
                            break;
                        }
                        if (judge(b[4*k+4],vec(b[4*k+4].x,10),b[i],b[j]))
                        {
                            flag=false;
                            break;
                        }    
                    }
                    dis[i][j]=(flag?dist(b[i],b[j]):INF);
                    dis[j][i]=dis[i][j];
                }
            for (k=0;k<=4*n+1;k++)
                for (i=0;i<=4*n+1;i++)
                    for (j=0;j<=4*n+1;j++)
                        dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
            printf("%.2f
    ", dis[0][4 * n + 1]);
        }    
        return 0;
    }
    View Code

    POJ - 2653

    求线段与线段相交

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    //#include<chrono>
    #include<vector>
    #include<list>
    #include<queue>
    #include<string>
    #include<set>
    #include<map>
    //#include<unordered_set>
    //#include<unordered_map>
    #define debug frelimiten("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    using namespace std;
    typedef long long ll;
    typedef double lf;
    typedef pair<int, int> pii;
    const int maxn = 100500+10;
    const int INF = 0x3f3f3f3f; 
    const int mod = 998244353;
    const double eps=1e-8;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    int sgn(double x)
    {
        if(fabs(x)<eps) return 0;
        if(x<0) return -1;
        else return 1;
    }
    struct vec{
        lf x,y;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
        lf operator ^(const vec &b){return x*b.y-y-b.x;}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    }b[maxn];
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd
        #define SJ(x) max(a.x,b.x)<min(c.x,d.x)
        || max(c.x,d.x)<min(a.x,b.x)
        if(SJ(x) || SJ(y))return 0;
        #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0
        return SJ2(a,b,c,d) && SJ2(c,d,a,b);
    }
    struct Line
    {
        vec s,t;
    }a[maxn];
    int n,i,j,num;
    bool vis[maxn],flag,firstt;
    double x1,y1,x2,y2;
    int main()
    {
        while (~scanf("%d",&n))
        {
            if (n==0) return 0;
            for (i=1;i<=n;i++)
            {
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                a[i].s=vec(x1,y1);
                a[i].t=vec(x2,y2);
            }
            memset(vis,0,sizeof(vis));
            printf("Top sticks:");
            firstt=0;
            for (i=1;i<=n;i++)
            {
                flag=0;
                for (j=i+1;j<=n;j++)
                {
                    if (judge(a[i].s,a[i].t,a[j].s,a[j].t)) 
                    {
                        flag=1;
                        break;
                    }
                }
                if (!flag) 
                {
                    if (!firstt) firstt=1;
                        else printf(",");
                    printf(" %d",i);
                }
            }    
            puts(".");
        }
    }
    View Code

    POJ - 1066

    中点通过,与通过线的任何方式无差异,问题还是转化为起点到终点通过几条线。

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    //#include<chrono>
    #include<vector>
    #include<list>
    #include<queue>
    #include<string>
    #include<set>
    #include<map>
    #define debug frelimiten("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    using namespace std;
    typedef long long ll;
    typedef double lf;
    typedef pair<int, int> pii;
    const int maxn = 1050+10;
    const int INF = 0x3f3f3f3f; 
    const int mod = 998244353;
    const double eps=1e-8;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    int sgn(double x)
    {
        if(fabs(x)<eps) return 0;
        if(x<0) return -1;
        else return 1;
    }
    struct vec{
        lf x,y;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
        lf operator ^(const vec &b){return x*b.y-y-b.x;}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    }q[maxn],pp;
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd
        #define SJ(x) max(a.x,b.x)<min(c.x,d.x)
        || max(c.x,d.x)<min(a.x,b.x)
        if(SJ(x) || SJ(y))return 0;
        #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0
        return SJ2(a,b,c,d) && SJ2(c,d,a,b);
    }
    int n,i,minn,j,num;
    double targetx,targety,x1,y1,x2,y2;
    int main()
    {
        n=read();
        for (i=1;i<=2*n;i+=2) 
        {
            scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
            q[i]=vec(x1,y1);
            q[i+1]=vec(x2,y2);
        }
        scanf("%lf%lf",&targetx,&targety);
        pp=vec(targetx,targety);
        minn=INF;
        for (i=1;i<=2*n;i++)
        {
            num=0;
            for (j=1;j<=2*n;j+=2)
            {
                if (judge(q[i],pp,q[j],q[j+1])) num++;
            }
            minn=min(minn,num);
        }
        if (!n) printf("Number of doors = 1");
        else printf("Number of doors = %d",minn);
        return 0;
    }
    View Code

    POJ - 1410

    在矩阵里面也算相交

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    //#include<chrono>
    #include<vector>
    #include<list>
    #include<queue>
    #include<string>
    #include<set>
    #include<map>
    #define debug frelimiten("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    using namespace std;
    typedef long long ll;
    typedef double lf;
    typedef pair<int, int> pii;
    const int maxn = 1050+10;
    const int INF = 0x3f3f3f3f; 
    const int mod = 998244353;
    const double eps=1e-8;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    int sgn(double x)
    {
        if(fabs(x)<eps) return 0;
        if(x<0) return -1;
        else return 1;
    }
    struct vec{
        lf x,y;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
        lf operator ^(const vec &b){return x*b.y-y-b.x;}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    }q[maxn],pp;
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    bool judge(vec a,vec b,vec c,vec d){ //线段ab和线段cd
        #define SJ(x) max(a.x,b.x)<min(c.x,d.x)
        || max(c.x,d.x)<min(a.x,b.x)
        if(SJ(x) || SJ(y))return 0;
        #define SJ2(a,b,c,d) cross(a-b,a-c)*cross(a-b,a-d)<=0
        return SJ2(a,b,c,d) && SJ2(c,d,a,b);
    }
    struct Line
    {
        vec s,t;
    }line,rectangle[5];
    bool flag;
    int n;
    double x,y,xx,yy;
    int main()
    {
        n=read();
        while (n--)
        {
            scanf("%lf%lf",&x,&y);
            line.s=vec(x,y);
            scanf("%lf%lf",&x,&y);
            line.t=vec(x,y);
            scanf("%lf%lf",&x,&y);
            scanf("%lf%lf",&xx,&yy);
            if (x>xx) swap(x,xx);
            if (y<yy) swap(y,yy);
            rectangle[1].s=vec(x,y),rectangle[1].t=vec(x,yy);
            rectangle[2].s=vec(x,y),rectangle[2].t=vec(xx,y);
            rectangle[3].s=vec(xx,yy),rectangle[3].t=vec(xx,y);
            rectangle[4].s=vec(xx,yy),rectangle[4].t=vec(x,yy);
            flag=0;
            for (int i=1;i<=4;i++)
            {
                if (judge(line.s,line.t,rectangle[i].s,rectangle[i].t))
                {
                    flag=1;
                    break;
                }
            }
            if (x<=line.s.x && line.s.x<=xx && yy<=line.s.y && line.s.y<=y) flag=1;
            if (x<=line.t.x && line.t.x<=xx && yy<=line.t.y && line.t.y<=y) flag=1;
            if (flag) printf("T
    ");
                else printf("F
    ");
        }
        return 0;
    }
    View Code

    POJ - 1696

    极角排序

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    //#include<chrono>
    #include<vector>
    #include<list>
    #include<queue>
    #include<string>
    #include<set>
    #include<map>
    #define debug frelimiten("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    using namespace std;
    typedef long long ll;
    typedef double lf;
    typedef pair<int, int> pii;
    const int maxn = 1050+10;
    const int INF = 0x3f3f3f3f; 
    const int mod = 998244353;
    const double eps=1e-8;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    int sgn(double x)
    {
        if(fabs(x)<eps) return 0;
        if(x<0) return -1;
        else return 1;
    }
    struct vec{
        lf x,y;
        int num;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
        lf operator ^(const vec &b){return x*b.y-y-b.x;}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    }p[maxn];
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    int t,n,i,ans[maxn];
    bool cmp(vec p1,vec p2)
    {
        double temp;
        temp=cross(p1,p2,p[i-1]);
        if (sgn(temp)>0) return true;
        else if (sgn(temp)==0 && ((p1-p[i-1]).len())<((p2-p[i-1]).len())) return true;
        return false;
    }
    
    int main()
    {
        t=read();
        while (t--)
        {
            n=read();
            for (i=0;i<n;i++)
            {
                p[i].num=read();
                cin>>p[i].x>>p[i].y;
                if (p[i].y<p[0].y) swap(p[0],p[i]);
            }
    //        sort(p+1,p+n,cmp);
            ans[0]=p[0].num;
            for (i=1;i<n;i++)
            {
                sort(p+i,p+n,cmp);
                ans[i]=p[i].num;
            }
            cout<<n;
            for (i=0;i<n;i++)
                printf(" %d",ans[i]);
            cout<<endl;
        }
        return 0;
    }
    View Code

    POJ - 3347

    这题看了别人的思路感觉十分的巧妙,首先我们把所以线增大√2倍,然后再通过对前者矩阵的比较,算出左端点和右端点,这时就可以一个个判断是否有遮挡即可。

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    //#include<chrono>
    #include<vector>
    #include<list>
    #include<queue>
    #include<string>
    #include<set>
    #include<map>
    #define debug frelimiten("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    using namespace std;
    typedef long long ll;
    typedef double lf;
    typedef pair<int, int> pii;
    const int maxn = 1050+10;
    const int INF = 0x3f3f3f3f; 
    const int mod = 998244353;
    const double eps=1e-8;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    int sgn(double x)
    {
        if(fabs(x)<eps) return 0;
        if(x<0) return -1;
        else return 1;
    }
    struct vec{
        lf x,y;
        int num;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
        lf operator ^(const vec &b){return x*b.y-y-b.x;}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    }p[maxn];
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    struct node
    {
        int l,r,len;
    };
    int n,i,j;
    int solve(node a,node b)
    {
        if (a.len<=b.len) return b.l+b.len+a.len;
            else return b.r+b.len-a.len;
    }
    int main()
    {
        node a[55];
        while (~scanf("%d",&n),n)
        {
            for (i=0;i<n;i++)
            {
                scanf("%d",&a[i].len);
                a[i].l=0;
                for (j=0;j<i;j++)
                    a[i].l=max(a[i].l,solve(a[i],a[j]));
                a[i].r=a[i].l+2*a[i].len;
            }
            for (i=1;i<n;i++)
                for (j=0;j<i;j++)
                {
                    if (a[i].len<a[j].len && a[i].l<a[j].r) a[i].l=a[j].r;
                    else if (a[i].len>a[j].len && a[i].l<a[j].r) a[j].r=a[i].l;
                }
            for (i=0;i<n;i++)
                if (a[i].l<a[i].r) printf("%d ",i+1);
            printf("
    ");
        }
        return 0;
    } 
    View Code

    POJ - 1039

    首先如果存在能通过这个管道的线,那么我们对这条线稍微转一下角度,必会有先交到两个点,所以枚举两个端点,如果这条过这两个端点的直线能够通过整个管道,则得到答案。

    若不能,我们每次取射到的最远距离即可。

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<cstdlib>
    #include<ctime>
    #include<iomanip>
    #include<cctype>
    #include<iostream>
    #include<algorithm>
    //#include<chrono>
    #include<vector>
    #include<list>
    #include<queue>
    #include<string>
    #include<set>
    #include<map>
    #define debug frelimiten("r.txt","r",stdin)
    #define mp make_pair
    #define ri register int
    using namespace std;
    typedef long long ll;
    typedef double lf;
    typedef pair<int, int> pii;
    const int maxn = 1050+10;
    const int INF = 0x3f3f3f3f; 
    const int mod = 998244353;
    const double eps=1e-8;
    const double PI=acos(-1.0);
    inline ll read(){ll s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return s*w;}
    ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
    int sgn(double x)
    {
        if(fabs(x)<eps) return 0;
        if(x<0) return -1;
        else return 1;
    }
    struct vec{
        lf x,y;
        int num;
        vec(lf x=0,lf y=0):x(x),y(y){}
        vec operator-(const vec &b){return vec(x-b.x,y-b.y);}
        vec operator+(const vec &b){return vec(x+b.x,y+b.y);}
        vec operator*(lf k){return vec(k*x,k*y);}
        lf operator ^(const vec &b){return x*b.y-y-b.x;}
        lf len(){return hypot(x,y);}
        lf sqr(){return x*x+y*y;}
        /*截取*/vec trunc(lf k=1){return *this*(k/len());}
        /*逆时针旋转*/vec rotate(double th){lf c=cos(th),s=sin(th); return vec(x*c-y*s,x*s+y*c);}
    }down[maxn],up[maxn];
    lf cross(vec a,vec b){return a.x*b.y-a.y*b.x;};
    lf cross(vec a,vec b,vec c){return cross(a-b,b-c);}
    lf dot(vec a,vec b){return a.x*b.x+a.y*b.y;}
    bool cmp_xy(const vec &a,const vec &b){return make_pair(a.x,a.y)<make_pair(b.x,b.y);}
    bool cmp_atan(const vec &a,const vec &b){return atan2(a.x,a.y)<atan2(b.x,b.y);}
    /*输出*/ostream &operator<<(ostream &o,const vec &v){return o<<'('<<v.x<<','<<v.y<<')';}
    bool judge(vec a,vec b,vec c,vec d)
    { 
        return (sgn(cross(a,b,c))*sgn(cross(a,b,d))<=0);
    }
    double solve(vec a,vec b,vec c,vec d)
    {
        lf area1=cross(a,b,c);
        lf area2=cross(a,b,d);
        int num1=sgn(area1);
        int num2=sgn(area2);
        if (num1*num2<0) return (area2*c.x-area1*d.x)/(area2-area1);
        if (num1*num2==0)
        {
            if (num1==0) return c.x;
            else return d.x;
        }
        return -INF;
    }
    double ans,maxx;
    int n,i,j,k;
    bool flag;
    int main()
    {
        while (~scanf("%d",&n))
        {
            if (n==0) return 0;
            for (i=1;i<=n;i++)
            {
                scanf("%lf%lf",&up[i].x,&up[i].y);
                down[i].x=up[i].x;
                down[i].y=up[i].y-1;
            }
            maxx=-INF;
            flag=false;
            for (i=1;i<=n&&!flag;i++)
                for (j=1;j<=n&&!flag;j++)
                    if (i!=j)
                    {
                        for (k=1;k<=n;k++)
                            if (!judge(up[i],down[j],up[k],down[k])) break;
                        if (k>n) 
                        {
                            flag=true;
                        }
                        else 
                        if (k>max(i,j))
                        {
                            ans=solve(up[i],down[j],up[k],up[k-1]);
                            if (maxx<ans) maxx=ans;
                            ans=solve(up[i],down[j],down[k],down[k-1]);
                            if (maxx<ans) maxx=ans;
                        }
                    }
            if(flag)
                cout<<"Through all the pipe."<<endl;
            else
                cout<<fixed<<setprecision(2)<<maxx<<endl;
        }
    }
    View Code
  • 相关阅读:
    道路和航线
    Sorting It All Out
    Sightseeing Cows(0/1分数规划+Spfa判负环)
    【模板】缩点
    间谍网络
    Tarjan算法专练
    数论知识点总结
    博客迁移到博客园
    第一届CCPC河南省赛
    find程序实现
  • 原文地址:https://www.cnblogs.com/Y-Knightqin/p/12995818.html
Copyright © 2020-2023  润新知