zoukankan      html  css  js  c++  java
  • Inheritance

    题目大意:给一个凸多边形(点不是按顺序给的),然后计算给出的线段在这个凸多边形里面的长度,如果在边界不计算。

    分析:WA2..WA3...WA4..WA11...WA的无话可说,总之细节一定考虑清楚,重合的时候一定是0

    代码如下:

    =========================================================================================================

    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    
    const int MAXN = 1007;
    const double EPS = 1e-14;
    const double FarX = 4e4+7;
    
    int Sign(double x)
    {
        if(x > EPS)return 1;
        if(fabs(x) < EPS)return 0;
        return -1;
    }
    struct point
    {
        double x, y;
        point(double x=0, double y=0):x(x),y(y){}
        point operator - (const point &t)const{
            return point(x-t.x, y-t.y);
        }
        bool operator == (const point &t)const{
            return Sign(x-t.x) ==0 && Sign(y-t.y) == 0;
        }
        double operator ^(const point &t)const{
            return x*t.y - y*t.x;
        }
        double operator *(const point &t)const{
            return x*t.x + y*t.y;
        }
    };
    double Dist(point t1, point t2)
    {
        return sqrt((t1-t2)*(t1-t2));
    }
    struct segment
    {
        point S, E;
        double a, b, c;///ax + by = c;
    
        segment(point S=0, point E=0):S(S), E(E){
            a = S.y - E.y;
            b = E.x - S.x;
            c = E.x*S.y - S.x*E.y;
        }
        int  Inter(const segment &tmp)const{
            int t1 = Sign((S-E)^(tmp.S-E));
            int t2 = Sign((S-E)^(tmp.E-E));
    
            if(t1 == 0 && t2 == 0)
                return -1;
    
            if(t1*t2 == -1)
                return 1;
            if(abs(t1+t2) == 1)///如果完全相交或者有一点相交,不考虑重合
                return 2;
            return false;
        }
        point crossNode(const segment &tmp)const
        {///两条线段的交点
            point result;
            result.x = (c*tmp.b-tmp.c*b) / (a*tmp.b-tmp.a*b);
            result.y = (c*tmp.a-tmp.c*a) / (b*tmp.a-tmp.b*a);
    
            return result;
        }
        bool OnSeg(const point &p)
        {///判断点是否在线段上
            if(Sign((S-E)^(p-E)) == 0)
            if(Sign((p.x-S.x)*(p.x-E.x)) <= 0)
            if(Sign((p.y-S.y)*(p.y-E.y)) <= 0)
                return true;
            return false;
        }
    };
    struct Polygon
    {
        int N;///有N个点
        point vertex[MAXN];
    
        int Point_In_Poly(const point &p)
        {///点在多边形里面1,还是外面-1,还是边上 0
            segment ray(p, point(FarX, p.y));
            int cnt = 0;
    
            for(int i=0; i<N; i++)
            {
                segment L(vertex[i], vertex[i+1]);
    
                if(L.OnSeg(p))
                    return 0;
    
                if(ray.OnSeg(L.S))
                {
                    if(L.E.y-L.S.y > EPS)
                        cnt ++;
                }
                else if(ray.OnSeg(L.E))
                {
                    if(L.S.y-L.E.y > EPS)
                        cnt ++;
                }
                else if(L.Inter(ray)==1 && ray.Inter(L)==1)
                    cnt++;
            }
    
            if(cnt % 2)
                return 1;
            return -1;
        }
        double Seg_In_Poly(const segment &L1)
        {///线段与多边形相交的长度,先求出线段与多边形有几个交点
            point p[10];
            int k=0;
    
            for(int i=0; i<N; i++)
            {
                segment L2(vertex[i], vertex[i+1]);
    
                if(L1.Inter(L2) == -1 && L2.Inter(L1) == -1)
                    return 0;
    
                if(k<2 && L1.Inter(L2) && L2.Inter(L1))
                {
                    point t = L1.crossNode(L2);
                    if(!k || !(p[0] == t) )
                        p[k++] = t;
                }
            }
    
            double len=0;
    
            if(k == 2)
            {///有两个不同的交点
                len = Dist(p[0], p[1]);
            }
            else if(k == 1)
            {///有一个交点,判断哪个端点在多边形内
                if(Point_In_Poly(L1.S) == 1)
                    len = Dist(p[0], L1.S);
                else if(Point_In_Poly(L1.E) == 1)
                    len = Dist(p[0], L1.E);
            }
            else if(Point_In_Poly(L1.S) == 1)
            {///没有交点的时候,判断线段是否在多边形内
                len = Dist(L1.S, L1.E);
            }
    
            return len;
        }
    };
    Polygon poly;
    
    bool cmp(point t1, point t2)
    {
        return Sign((t2-poly.vertex[0])^(t1-poly.vertex[0])) < 0;
    }
    
    int main()
    {
        int i, M, ki=0;
    
        scanf("%d", &poly.N);
    
        for(i=0; i<poly.N; i++)
        {
            scanf("%lf%lf", &poly.vertex[i].x, &poly.vertex[i].y);
            if(poly.vertex[ki].y > poly.vertex[i].y ||
               (poly.vertex[ki].y == poly.vertex[i].y && poly.vertex[ki].x > poly.vertex[i].x) )
               ki = i;
        }
    
        swap(poly.vertex[0], poly.vertex[ki]);
        sort(poly.vertex+1, poly.vertex+poly.N, cmp);
        poly.vertex[poly.N] = poly.vertex[0];
    
        scanf("%d", &M);
    
        while(M--)
        {
            point A, B;
    
            scanf("%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y);
            segment L(A, B);
            printf("%.6f
    ",poly.Seg_In_Poly(L));
        }
    
        return 0;
    }
    /**
    6
    1 2
    2 1
    2 3
    3 1
    3 3
    4 2
    200
    1 1 4 10
    **/
  • 相关阅读:
    python类库31[正则表达式匹配实例]
    Mysql百万级数据迁移实战笔记
    面试官:一千万数据,怎么快速查询?
    为什么MySQL不建议使用NULL作为列默认值?
    Redis各个数据类型最大存储量
    Rabbitmq延迟队列实现定时任务
    PHPstorm批量修改文件换行符CRLF为LF
    使用SeasLog打造高性能日志系统
    协程编程注意事项
    Rabbitmq 安装过程中常见问题(亲测可行)
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4839108.html
Copyright © 2011-2022 走看看