第八届福建省大学生程序设计竞赛 FZU 2273 Triangles (计算几何)

来源:互联网 发布:淘宝网店策划案怎么写 编辑:程序博客网 时间:2024/06/05 20:26

题目原文:http://acm.fzu.edu.cn/problem.php?pid=2273

Problem B Triangles

Accept: 158    Submit: 754
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


题目大意:给定两个三角形六个顶点,判断两个三角形的关系(相交、相离、包含)

解题思路:

(1)通过叉积判断点与线的关系,点与这条边对应的那个顶点位于这条边的同一侧,说明这个点在这条边的内测。如果一个点位于三条边的内侧,则这个点在三角形内。如果三个顶点都在这个三角形内,说明两个三角形是包含关系。

(2)通过判断线段相交的关系,可以确定两个三角形是否存在边相交

(3)其余情况说明两个三角形相离。

AC代码:

/*    @Author: wchhlbt    @Date:   2017/7/17*/#include <vector>#include <list>#include <map>#include <set>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iostream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <ctime>#include <cstring>#include <limits>#include <climits>#include <cstdio>#define Fori(x) for(int i=0;i<x;i++)#define Forj(x) for(int j=0;j<x;j++)#define maxn 10007#define inf 0x3f3f3f3f#define ONES(x) __builtin_popcount(x)#define _  << "  " <<using namespace std;typedef long long ll ;const double eps =1e-8;const int mod = 1000000007;typedef pair<int, int> P;const double PI = acos(-1.0);int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};typedef struct  Point{    double x,y;    Point(double x=0,double y=0):x(x),y(y){}}Vector;Vector operator + (const Vector & A,const Vector & B) { return Vector(A.x+B.x,A.y+B.y);}Vector operator - (const Point & A,const Point & B) { return Vector(A.x-B.x,A.y-B.y);}Vector operator * (const Vector & A,double p) { return Vector(A.x*p,A.y*p);}Vector operator / (const Vector & A,double p) { return Vector(A.x/p,A.y/p);}bool operator < (const Point &A, const Point &B){    return A.x<B.x||(A.x==B.x&&A.y<B.y);}int dcmp(double x){    if(fabs(x)<eps) return 0;    return  x<0? -1 : 1 ;}bool operator == (const Point &A,const Point &B){    return dcmp(A.x-B.x)==0&&dcmp(A.y-B.y)==0;}//向量点乘double Dot(const Vector &A, const Vector &B) {  return A.x*B.x+A.y*B.y;  }//求向量的长度或两点距离double Length(const Vector &A){ return sqrt(Dot(A,A)); }//返回两个向量夹角的弧度值double Angle(const Vector &A, const Vector &B){    return  acos(Dot(A,B)/Length(A)/Length(B));}//向量叉积。共起点的两个向量A,B,若A叉乘B大于0,则B在A的左边。double Cross(const Vector &A, const Vector &B){ return A.x*B.y-A.y*B.x ;}//用叉积求三个点组成的三角形的面积。面积为0表示三点共线。double Area2(const Point &A,const Point &B,const Point &C ){return Cross(B-A,C-A) ;}//向量绕起点旋转,rad为逆时针旋转的弧度。//Rotate(A,-rad)表示将A顺时针旋转radVector Rotate(const Vector &A,double rad){    return Vector(A.x*cos(rad)-A.y*sin(rad),A.x*sin(rad)+A.y*cos(rad));}//计算A向量的单位法向量,即左转90度,将单位归一化//调用前确保A向量不是零向量Vector Normal(Vector A){    double L=Length(A);    return Vector(-A.y/L,A.x/L);}//用直线的参数方程(P=P0+t*v,P0是直线上任意一点,v是直线的方向向量)求两直线的交点坐标Point GetLineIntersection(const Point & P,const Vector & v,const Point & Q,const Vector & w){    Vector u=P-Q;    double t=Cross(w,u)/Cross(v,w);    return P+v*t;}//点到直线的距离。平行四边形面积除以底double DistanceToLine(const Point & P,const Point & A,const Point & B){    Vector v1=B-A,v2=P-A;    return fabs(Cross(v1,v2))/Length(v1);}//点到线段的距离double DistanceToSegment(const Point & P,const Point & A,const Point & B){    if(A==B)  return Length(P-A);    Vector v1=B-A,v2=P-A,v3=P-B;    if(dcmp(Dot(v1,v2))<0) return Length(v2);    else if(dcmp(Dot(v1,v3))>0) return Length(v3);    else return fabs(Cross(v1,v2))/Length(v1);}//点在直线上的投影Point GetLineProjection(const Point & P,const Point & A,const Point & B){    Vector v=B-A;    return A+v*(Dot(v,P-A)/Dot(v,v));}//判断点P是否在线段AB(不含端点)上bool OnSegment(const Point & P,const Point & A,const Point & B){    return dcmp(Cross(A-P,B-P))==0 && dcmp(Dot(A-P,B-P)) <0 ;}//判断两线段是否规范相交(两条线段恰有一个公共点且不在任何一个线段的端点)bool SegmentProperIntersection(const Point & a1,const Point & a2,const Point & b1,const Point & b2){    double c1=Cross(a2-a1,b1-a1) ,c2=Cross(a2-a1,b2-a1);    double c3=Cross(b2-b1,a1-b1) ,c4=Cross(b2-b1,a2-b1);    return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0 ;}//判断两线段是否规范相交(两条线段可以部分重合或者相交在某一个线段的端点)bool SegmentIntersection(const Point & a1,const Point & a2,const Point & b1,const Point & b2){    double c1=Cross(a2-a1,b1-a1) ,c2=Cross(a2-a1,b2-a1);    double c3=Cross(b2-b1,a1-b1) ,c4=Cross(b2-b1,a2-b1);    return dcmp(c1)*dcmp(c2)<=0 && dcmp(c3)*dcmp(c4)<=0 ;}bool SameSide(Point A, Point B, Point C, Point D)//C和D是否在AB同一侧{    Vector AB = B-A;    Vector AC = C-A;    Vector AD = D-A;    double aaa = Cross(AB,AC);    double bbb = Cross(AB,AD);    if(aaa*bbb>=0)  return true;    // v1 and v2 should point to the same direction    return false;}// Same side method// Determine whether point D in triangle ABCbool PointinTriangle1(Point A, Point B, Point C, Point D){    return SameSide(A, B, C, D) &&        SameSide(B, C, A, D) &&        SameSide(C, A, B, D) ;}int main(){    int t;    cin>>t;    while(t--){        int flag = 0;        Point p[6];        for(int i = 0; i<6; i++)            cin>>p[i].x>>p[i].y;        for(int i = 0; i<3; i++){            if(SegmentIntersection(p[i],p[(i+1)%3],p[3],p[4]) || SegmentIntersection(p[i],p[(i+1)%3],p[3],p[5]) || SegmentIntersection(p[i],p[(i+1)%3],p[5],p[4]))            {                flag = 1;                break;            }        }        if(flag==1){            cout << "intersect" << endl;            continue;        }        if(PointinTriangle1(p[0],p[1],p[2],p[3]) && PointinTriangle1(p[0],p[1],p[2],p[4]) && PointinTriangle1(p[0],p[1],p[2],p[5])){            cout << "contain" << endl;            continue;        }        if(PointinTriangle1(p[3],p[4],p[5],p[0]) && PointinTriangle1(p[3],p[4],p[5],p[1]) && PointinTriangle1(p[3],p[4],p[5],p[2])){            cout << "contain" << endl;            continue;        }        cout << "disjoint" << endl;    }    return 0;}


阅读全文
0 0
原创粉丝点击