• FZUOJ-2273 Triangles


     Problem 2273 Triangles

    Accept: 109    Submit: 360
    Time Limit: 1000 mSec    Memory Limit : 262144 KB

     Problem Description

    This is a simple problem. Given two triangles A and B, you should determine they are intersect, contain or disjoint. (Public edge or point are treated as intersect.)

     Input

    First line contains an integer T (1 ≤ T ≤ 10), represents there are T test cases.

    For each test case: X1 Y1 X2 Y2 X3 Y3 X4 Y4 X5 Y5 X6 Y6. All the coordinate are integer. (X1,Y1) , (X2,Y2), (X3,Y3) forms triangles A ; (X4,Y4) , (X5,Y5), (X6,Y6) forms triangles B.

    -10000<=All the coordinate <=10000

     Output

    For each test case, output “intersect”, “contain” or “disjoint”.

     Sample Input

    20 0 0 1 1 0 10 10 9 9 9 100 0 1 1 1 0 0 0 1 1 0 1

     Sample Output

    disjoint intersect

     Source

    第八届福建省大学生程序设计竞赛-重现赛(感谢承办方厦门理工学院)

    链接:http://acm.fzu.edu.cn/contest/problem.php?cid=156&sortid=2

    题意:给出两个三角形A,B的三个点的坐标,判断这两个三角形的位置关系,分为包含(contain),相交(intersect),不相交(disjoint)三种关系,特别的,边或者点重合也属于相交;

    思路:可以先判断A的某一条边是否和B的某一条边相交(包括点重合和边重合)来判断相交关系,然后可以根据三角形A(B)的一个定点是否在三角形B(A)内来判断包含关系;如不满足前两种关系,则三角形A,B便满足第三种关系;判断某一点是否在三角形内可以用面积法来判断,若点P在三角形内部(包括边上),则有S(ABC)=S(ABP)+S(APC)+S(BPC);否则有S(ABC)小于三个小三角形面积之和;三角形的面积可以利用向量积(叉积)来做,S=|ABxAC|/2;

    ps:(如果下面的分析有误,欢迎指出,代码有参考模板)

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #define eps 1e-8
    #define zero(x) (((x)>0?(x):(-x))<eps)
     
    using namespace std;
     
    struct point{double x,y;};
    struct triangle{point a,b,c;};
     
    ///计算叉积
    /**
    设向量A=p1-p0,B=p2-p0;
        |     i           j       k   |
    AxB=| p1.x-p0.x   p1.y-p0.y   0   |
        | p2.x-p0.x   p2.y-p0.y   0   |
    */
     
    double xmult(point p1,point p2,point p0){
        return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
    }
     
    ///判断三点共线
    /**
    若三点共线 设向量A=p1-p0,B=p2-p0;
    |AxB|=|A||B|sin<A,B>,又三点共线,所以<A,B>=0,所以|AxB|=0;
    */
    int dots_inline(point p1,point p2,point p3){
        return zero(xmult(p1,p2,p3));
    }
    ///判断两点在线段同侧
    /**
    设向量 A=l2-l1,B=p2-l1,C=p1-l1;
    由右手定则可以得出,若p1,p2两点同侧,则|AxB|与|AxC|同正负;
    若p1或p2在线段上,则|AxC|或|AxB|等于0
    */
    int same_side(point p1,point p2,point l1,point l2){
        return xmult(l1,p1,l2) * xmult(l1,p2,l2) > eps;
    }
    ///判断点是否在线上,包括端点
    /**
    1.先判三点共线;
    2.再判点是否在线段上,如果在,则两个端点的横坐标与该点的横坐标(纵坐标)之差的积小于或者等于零;
    */
    int dot_online_in(point p,point l1,point l2){
        return zero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x) < eps && (l1.y-p.y)*(l2.y-p.y) < eps;
    }
     
    ///判断两线相交,包括部分重合和点重合
    /**
    1.先判是否共线,如果不共线,看其中一条边的两个端点是否在另一条线段的两侧;
    2.判断点是否在线段上;
    */
    int intersect_in(point u1,point u2,point v1,point v2){
        if(!dots_inline(u1,u2,v1)||!dots_inline(u1,u2,v2))
            return !same_side(u1,u2,v1,v2) && !same_side(v1,v2,u1,u2);
        return dot_online_in(u1,v1,v2)||dot_online_in(u2,v1,v2)||dot_online_in(v1,u1,u2)||dot_online_in(v2,u1,u2);
    }
     
    ///计算面积
    /**
    S=|AxB|/2;
    */
    double area_triangle(point p1,point p2,point p3){
        return fabs(xmult(p1,p2,p3))/2;
    }
    ///判断点是否包含在三角形内部,包括三条边上
    /**
    大三角形与三个小三角形的面积之差是否为零
    */
    int dot_triangle_in(triangle p1,point p0){
        return fabs(area_triangle(p1.a,p1.b,p1.c)-area_triangle(p1.a,p1.b,p0)-area_triangle(p1.a,p0,p1.c)-area_triangle(p0,p1.b,p1.c))<eps;
    }
     
    void solve_question(){
        point a[3],b[3];
        triangle A,B;
        for(int i=0;i<3;i++)
            cin >> a[i].x >> a[i].y;
        for(int i=0;i<3;i++)
            cin >> b[i].x >> b[i].y;
        A = (triangle){a[0],a[1],a[2]};
        B = (triangle){b[0],b[1],b[2]};
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
                if(intersect_in(a[i],a[(i+1)%3],b[j],b[(j+1)%3])) { printf("intersect
    ");return;}
        if(dot_triangle_in(A,b[0]) || dot_triangle_in(B,a[0]))
            printf("contain
    ");
        else
            printf("disjoint
    ");
     
    }
     
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            solve_question();
        }
    }


  • 相关阅读:
    myeclipse连接并运行sql文件
    搜集的一些常用的方法
    使用SolrJ代码导入,发布搜索服务
    solr客户端的使用
    Ubuntu搭建solr搜索服务器
    Intersecting Lines(叉积,方程)
    Labyrinth(记忆化BFS)
    Segments(叉积)
    TOYS(叉积)
    Treasures and Vikings(两次搜索)
  • 原文地址:https://www.cnblogs.com/Pretty9/p/7347668.html
Copyright © 2020-2023  润新知