hdu6590 2019 Multi-University Training Contest 1 Code

题解:

判断凸包相交的时候本来想算交面积的,然后想了想这样是不行的,因为交面积=0有可能是凸包顶点相交。然后题目数据量只有100个点而且还得分成两个集合,所以直接跑一下n^2的暴力就可以了

#include <bits/stdc++.h>
using namespace std;
#define maxn  int(1e2+5)
const long long  INF=1e18;
const double eps = 1e-6;
const double pi = acos (-1.0);
typedef long long int ll;
int dcmp(double x){
    if(fabs(x)<eps)return 0;
    else if(x>0)return 1;
    else return -1; 
}
double sqr(double x){return x*x;}
struct Point {
    double x, y;
    Point (double _x = 0, double _y = 0):x(_x), y(_y) {}
    void input () {scanf ("%lf%lf", &x, &y);}
    void output () {printf ("%.2f %.2f\n", x, y);}
    friend istream &operator >>(istream &os,Point &b){
        os>>b.x>>b.y;
        return os;
    }
    friend ostream &operator <<(ostream &os,Point &b){
        os<<b.x<<' '<<b.y;
        return os;
    }
    bool operator == (const Point &b) const {
        return (dcmp (x-b.x) == 0 && dcmp (y-b.y) == 0);
    }
    bool operator !=(const Point &b)const{
        return !((dcmp(x-b.x)==0&&dcmp(y-b.y)==0));
    }
    bool operator < (const Point &b) const {
        return (dcmp (x-b.x) == 0 ? dcmp (y-b.y) < 0 : x < b.x);
    }
    double operator ^(const Point &b)const{     //叉积
        return x*b.y-y*b.x;
    }
    Point operator + (const Point &b) const {
        return Point (x+b.x, y+b.y);
    }
    Point operator - (const Point &b) const {
        return Point (x-b.x, y-b.y);
    }
    Point operator * (double a) {
        return Point (x*a, y*a);
    }
    Point operator / (double a) {
        return Point (x/a, y/a);
    }
    double len2 () {//返回长度的平方
        return sqr (x) + sqr (y);
    }
    double len () {//返回长度
        return sqrt (len2 ());
    }
    double polar(){ //向量的极角
        return atan2(y,x);   //返回与x轴正向夹角(-pi~pi]
    }
    Point change_len (double r) {//转化为长度为r的向量
        double l = len ();
        if (dcmp (l) == 0) return *this;//零向量返回自身
        r /= l;
        return Point (x*r, y*r);
    }
    Point rotate_left () {//顺时针旋转90度
        return Point (-y, x);
    }
    Point rotate_right () {//逆时针旋转90度
        return Point (y, -x);
    }
    Point rotate (Point p, double ang) {//绕点p逆时针旋转ang
        Point v = (*this)-p;
        double c = cos (ang), s = sin (ang);
        return Point (p.x + v.x*c - v.y*s, p.y + v.x*s + v.y*c);
    }
    Point normal () {//单位法向量
        double l = len ();
        return Point (-y/l, x/l);
    }
};
  
double cross (Point a, Point b) {//叉积
    return a.x*b.y-a.y*b.x;
}
double dis (Point a, Point b) {//两个点的距离
    Point p = b-a; return p.len ();
}
int convex_hull (Point *p, Point *ch, int n) {//求凸包//更新:按照逆时针输出
    //所有的点集 凸包点集 点集的点数
    sort (p, p+n);
    int m = 0;
    for (int i = 0; i < n; i++) {
        while (m > 1 && cross (ch[m-1]-ch[m-2], p[i]-ch[m-1]) <= 0)
            m--;
        ch[m++] = p[i];
    }
    int k = m;
    for (int i = n-2; i >= 0; i--) {
        while (m > k && cross (ch[m-1]-ch[m-2], p[i]-ch[m-1]) <= 0)
            m--;
        ch[m++] = p[i];
    }
    if (n > 1)
        m--;
    return m;
}
double dot (Point a, Point b) {//点积
    return a.x*b.x + a.y*b.y;
}
struct Line {
    Point s, e;//直线的两个点
    Line () {}
    Line (Point _s, Point _e) : s(_s), e(_e) {}
    //一个点和倾斜角确定直线
    Line (Point p, double ang) {
        s = p;
        if (dcmp (ang-pi/2) == 0) {
            e = s + Point (0, 1);
        }
        else
            e = s + Point (1, tan (ang));
    }
    //ax+by+c=0确定直线
    Line (double a, double b, double c) {
        if (dcmp (a) == 0) {
            s = Point (0, -c/b);
            e = Point (1, -c/b);
        }
        else if (dcmp (b) == 0) {
            s = Point (-c/a, 0);
            e = Point (-c/a, 1);
        }
        else {
            s = Point (0, -c/b);
            e = Point (1, (-c-a)/b);
        }
    }
    void input () {
        s.input ();
        e.input ();
    }
    void adjust () {
        if (e < s) swap (e, s);
    }
    double polar(){ //极角
        return atan2(e.y-s.y,e.x-s.x);   //返回与x轴正向夹角(-pi~pi]
    }
    double length () {//求线段长度
        return dis (s, e);
    }
    double angle () {//直线的倾斜角
        double k = atan2 (e.y-s.y, e.x-s.x);
        if (dcmp (k) < 0) k += pi;
        if (dcmp (k-pi) == 0) k -= pi;
        return k;
    }
    Point operator &(const Line &b)const{    //求两直线交点
        Point res=s;
        double t=((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
        res.x+=(e.x-s.x)*t;
        res.y+=(e.y-s.y)*t;
        return res;
    }
};


double convex_circumference (Point *p, int n) {//多边形的周长(凹凸都可以)
    double ans = 0;
    for (int i = 0; i < n; i++) {
        ans += dis (p[i], p[(i+1)%n]);
    }
    return ans;
}
bool point_on_seg (Point p, Line l) {//判断点在线段上
    return dcmp (cross (p-l.s, l.e-l.s)) == 0 &&
    dcmp (dot (p-l.s, p-l.e) <= 0);
    //如果忽略端点交点改成小于号就好了
}
  

int relation (Point a, Point *b, int n) {//点和多边形的关系(凸凹都可以)
    //0:外部 1:内部 2:边上 3:顶点
    int w = 0;
    for (int i = 0; i < n; i++) {
        if (a == b[i] || a == b[(i+1)%n])
            return 3;
        if (point_on_seg (a, Line (b[(i+1)%n], b[i])))
            return 2;
        int k = dcmp (cross (b[(i+1)%n]-b[i], a-b[i]));
        int d1 = dcmp (b[i].y - a.y);
        int d2 = dcmp (b[(i+1)%n].y - a.y);
        if (k > 0 && d1 <= 0 && d2 > 0)
            w++;
        if (k < 0 && d2 <= 0 && d1 > 0)
            w--;
    }
    if (w != 0)
        return 1;
    return 0;
}
Point p1[maxn],p2[maxn],t1[maxn],t2[maxn];
int c1=0,c2=0;
int main()
{   
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        c1=0,c2=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            double xi1,xi2;int yi;
            scanf("%lf%lf%d",&xi1,&xi2,&yi);
            if(yi==-1)p1[c1++]=Point(xi1,xi2);
            else p2[c2++]=Point(xi1,xi2);
        }
        c1=convex_hull(p1,t1,c1),c2=convex_hull(p2,t2,c2);
        int flag=1;
        for(int i=0;i<c1;i++){
            if(relation(t1[i],t2,c2)>=1)flag=0;
        }
        for(int i=0;i<c2;i++){
            if(relation(t2[i],t1,c1)>=1)flag=0;
        }
        if(flag)printf("Successful!\n");
        else printf("Infinite loop!\n");
    }
    
}

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值