HDU 6590 Code(凸包相交)

Code

略,见Code

比赛的时候只看了看题目,没有具体思路,比赛完,题解说是凸包相交问题,以前没写过。补一发

#include <bits/stdc++.h>

using namespace std;
#define me(x,y) memset(x,y,sizeof x)
#define MIN(x,y) x < y ? x : y
#define MAX(x,y) x > y ? x : y

typedef long long ll;
typedef unsigned long long ull;

const int maxn = 1e6;
const double INF = 0x3f3f3f3f;
const int MOD = 1e9+7;
const int eps = 1e-8;

const double inf=1e20;
const double pi = acos(-1.0);
const int maxp = 1010;
/**
 * Compares a double to zero
 */
int sgn(double x){
    if(fabs(x) < eps) return 0;
    if(x < 0)return -1;
    else return 1;
}

struct Point{
    double x,y;
    Point(){}
    Point(double _x,double _y){x = _x,y = _y;}
    void input(){scanf("%lf%lf",&x,&y);}
    void output(){printf("%.2f %.2f\n",x,y);}
    bool operator == (Point b)const{return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;}
    bool operator < (Point b)const{return sgn(x-b.x) == 0 ? sgn(y-b.y)<0 : x<b.x;}
    Point operator -(const Point &b)const{return Point(x-b.x,y-b.y);}
    /**
     * 叉积
     */
    double operator ^ (const Point &b)const{return x*b.y-y*b.x;}    
    /**
     * 点积
     */
    double operator * (const Point &b)const{return x*b.x+y*b.y;}    
    /**
     * 返回两点间距离
     */
    double distance(Point p){return hypot(x-p.x,y-p.y);} 
};

struct Line{
    Point s,e;
    Line(){}
    Line(Point _s,Point _e){s = _s;e = _e;}
    bool operator == (Line v){return (s == v.s) && (e == v.e);}
    /**
     * 点在线段上的判断
     */
    bool  pointonseg(Point p){return sgn((p-s)^(e-s)) == 0 && sgn((p-s)^(e-s)) <= 0;}  
    void input(){s.input();e.input();}                              
    void adjust(){if(e < s) swap(s,e);}
    /**
     * 两线段相交判断
     * 2规范相交
     * 1非规范相交
     * 0不相交
     */
    int segcrosseg(Line v){                                         
        int d1 = sgn((e-s)^(v.s-s));
        int d2 = sgn((e-s)^(v.e-s));
        int d3 = sgn((v.e-v.s)^(s-v.s));
        int d4 = sgn((v.e-v.s)^(e-v.s));
        if((d1^d2) == -2 && (d3^d4) == -2)return 2;
        return (d1 == 0 && sgn((v.s-s)*(v.s-e)) <= 0) || 
               (d2 == 0 && sgn((v.e-s)*(v.e-e)) <= 0) ||
               (d3 == 0 && sgn((s-v.s)*(s-v.e)) <= 0) ||
               (d4 == 0 && sgn((e-v.s)*(e-v.e)) <= 0);
    }
};


struct polygon{
    int n;
    Point p[maxp];
    Line l[maxp];

    void getline(){
        for(int i = 0; i < n; ++i){
            l[i] = Line(p[i],p[(i+1)%n]);
        }
    }

    /**
     * 得到凸包,内部点编号为0-n-1,如果有影响判断所有点共点或共线
     */
	void getconvex(polygon &convex){                

        sort(p,p+n);
        convex.n = n;
        for(int i = 0;i < min(n,2); ++i)convex.p[i] = p[i];
        if(convex.n == 2 && (convex.p[0] == convex.p[1]))convex.n--;
        if(n <= 2)return ;
        int &top = convex.n;
        top = 1;
        for(int i = 2; i <n ; ++i){
            while(top && sgn((convex.p[top]-p[i])^(convex.p[top-1]-p[i])) <= 0){top--;}
            convex.p[++top] = p[i];
        }
        int temp = top;
        convex.p[++top] = p[n-2];
        for(int i = n-3; i >= 0; i--){
            while(top != temp && sgn((convex.p[top]-p[i])^(convex.p[top-1]-p[i])) <= 0)top--;
            convex.p[++top] = p[i];
        }
        if(convex.n == 2 && (convex.p[0] == convex.p[1]))convex.n--;
        //convex.norm();
    }
    /**
     * 判断点和任意多边形的关系
     * 3点上
     * 2边上
     * 1内部
     * 0外部
     */
    int relationpoint(Point q){
        for(int i = 0; i < n; ++i){
            if(p[i] == q) return 3;
        }
        getline();
        for(int i = 0; i < n; ++i){
            if(l[i].pointonseg(q)) return 2;
        }
        int cnt = 0;
        for(int i = 0; i < n; ++i){
            int j = (i+1)%n;
            int k = sgn((q-p[j])^(p[i]-p[j]));
            int u = sgn(p[i].y-q.y);
            int v = sgn(p[j].y-q.y);
            if(k > 0 && u < 0 && v >= 0) cnt++;
            if(k < 0 && v < 0 && u >= 0) cnt--;
        }
        return cnt!=0;
    }

    /**
     * 判断两凸包相交
     */
    bool ConvexHullIntersection(polygon convex){
        for(int i = 0; i < convex.n; ++i){
            if(relationpoint(convex.p[i])) return true;
        }
        for(int i = 0; i < n; ++i){
            if(convex.relationpoint(p[i])) return true;
        }
        getline();
        convex.getline();
        for(int i = 0; i < n; ++i){
            for(int j = 0; j < convex.n; ++j){
                if(l[i].segcrosseg(convex.l[j])) return true;
            }
        }
        return false;
    }
};


polygon co[2];
polygon convex[2];
int main(){
    int t;cin>>t;
    while(t--){
        int n;cin>>n;
        int tot_p0=0,tot_p1=0;
        for(int i = 1; i <= n; ++i){
            int x1,x2,y;
            scanf("%d%d%d",&x1,&x2,&y);
            if(y < 0) co[1].p[tot_p1++]=Point(x1,x2);
            else co[0].p[tot_p0++]=Point(x1,x2);
        }
        co[0].n=tot_p0;
        co[1].n=tot_p1;
        co[0].getconvex(convex[0]);
        co[1].getconvex(convex[1]);
        if(convex[0].ConvexHullIntersection(convex[1])) puts("Infinite loop!");
        else puts("Successful!");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值