zoukankan      html  css  js  c++  java
  • hdu多校第一场 1013(hdu6590)Code 凸包交

    题意:

    给定一组(x1,x2,y),其中y为1或0,问是否有一组(w1,w2,b),使得上述的每一个(x1,x2,y)都满足x1*w1+x2*w2+b在y=1时大于0,在y=-1时小于0.

    题解:

    赛时想的是半平面交,wa到哭

    后来看题解,居然那么简单?

    我们把x1,x2看成两个坐标轴,那么其实(w1,w2,b)对应着一条直线,x1*w1+x2+w2+b=0,那么令这个值大于0的必定在这条直线一边,令这个值小于0的必定在这个直线另一边。这道题也就是在问,有没有一条线能分隔开这两种点。

    那么把这两组点分别求出凸包,再去判断凸包有没有交就行了。注意,如果点在线上,那么上述式子算出来就得0了,因此两个凸包必须严格不交,点或边重合也不行。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define LL long long
    typedef pair<int,int> pii;
    const int inf = 0x3f3f3f3f;
    const int N =1e5+10;
    #define clc(a,b) memset(a,b,sizeof(a))
    const double eps = 1e-8;
    const int MOD = 1e9+7;
    void fre() {freopen("in.txt","r",stdin);}
    void freout() {freopen("out.txt","w",stdout);}
    inline int read() {int x=0,f=1;char ch=getchar();while(ch>'9'||ch<'0') {if(ch=='-') f=-1;ch=getchar();}while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
    
    int sgn(double x) {
        if(fabs(x) < eps)return 0;
        if(x < 0)return -1;
        else return 1;
    }
    
    struct Point {
        int x,y;
        Point() {}
        Point(int _x,int _y) {
            x = _x;
            y = _y;
        }
        Point operator -(const Point &b)const {
            return Point(x - b.x,y - b.y);
        }
        int operator ^(const Point &b)const {
            return x*b.y - y*b.x;
        }
        int operator *(const Point &b)const {
            return x*b.x + y*b.y;
        }
        friend int dis2(Point a) {
            return a.x*a.x+a.y*a.y;
        }
        friend bool operator<(const Point &a,const Point &b){
            if(fabs(a.y-b.y)<eps) return a.x<b.x;
            return a.y<b.y;
        }
    };
    typedef Point Vector;
    double Dot(Point A, Point B){return A.x*B.x+A.y*B.y;}//点积
    double Cross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}//叉积 
    double Length(Vector A){return sqrt(Dot(A,A));}//OA长  
    double Angle(Point A,Point B){return acos(Dot(A,B)/Length(A)/Length(B));}//OA和OB的夹角  
    //判断线段相交,不在端点相交  
    bool SegmentProperIntersection(Point a1,Point a2,Point b1,Point b2){  
        double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1),c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);  
        return sgn(c1)*sgn(c2)<0&&sgn(c3)*sgn(c4)<0;  
    }
    
    int graham(Point p[],int n,Point q[]){
         int top=1;
         sort(p,p+n);
         if(n==0) return 0;
         q[0]=p[0];
         if(n==1) return 1;
         q[1]=p[1];
         if(n==2) return 2;
         q[2]=p[2];
         for(int i=2;i<n;i++){
             while(top&&(Cross(q[top]-q[top-1],p[i]-q[top-1])<=0)) top--;
             q[++top]=p[i];
         }
         int len=top;
         q[++top]=p[n-2];
         for(int i=n-3;i>=0;i--){
             while(top!=len&&(Cross(q[top]-q[top-1],p[i]-q[top-1])<=0)) top--;
             q[++top]=p[i];
         }
         return top;
    }
    
    bool C_S(Point *ch1,int t1,Point *ch2,int t2)//判断凸包是否相交  
    {  
        double angle[1010],x;  
        int i,j,k,m;  
        if(t1==1)return true;  
        if(t1==2)  
        {  
            for(i=0;i<t2;i++)  
            {  
                k=sgn(Cross(ch1[1]-ch1[0],ch2[i]-ch1[0]));  
                if(k==0&&Dot(ch1[1]-ch1[0],ch2[i]-ch1[0])>0)  
                {  
                    if(Length(ch2[i]-ch1[0])<Length(ch1[1]-ch1[0]))break;  
                }  
            }  
            if(i<t2)return false;  
            if(t2==2&&SegmentProperIntersection(ch1[0],ch1[1],ch2[0],ch2[1]))return false;  
            return true;  
        }  
        angle[0]=0;  
        for(i=2;i<t1;i++)  
        angle[i-1]=Angle(ch1[1]-ch1[0],ch1[i]-ch1[0]);  
        for(i=0;i<t2;i++)  
        {  
            j=sgn(Cross(ch1[1]-ch1[0],ch2[i]-ch1[0]));  
            if(j<0||(j==0&&Dot(ch1[1]-ch1[0],ch2[i]-ch1[0])<0))continue;  
            j=sgn(Cross(ch1[t1-1]-ch1[0],ch2[i]-ch1[0]));  
            if(j>0||(j==0&&Dot(ch1[t1-1]-ch1[0],ch2[i]-ch1[0])<0))continue;  
            x=Angle(ch1[1]-ch1[0],ch2[i]-ch1[0]);  
            m=lower_bound(angle,angle+t1-1,x)-angle;  
            if(m==0)j=0;  
            else j=m-1;  
            k=sgn(Cross(ch1[j+1]-ch2[i],ch1[j+2]-ch2[i]));  
            if(k>=0)break;  
        }  
        if(i<t2)return false;  
        return true;  
    }
    
    Point p1[300],p2[300],ch1[300],ch2[300];
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            int n;
            scanf("%d",&n);
            int cnt1=0,cnt2=0;
            for(int i=0;i<n;i++){
                int x,y,c;
                scanf("%d%d%d",&x,&y,&c);
                if(c==0){
                    p1[cnt1++]=Point(x,y);
                }
                else p2[cnt2++]=Point(x,y);
            }
            int t1=graham(p1,cnt1,ch1);
            int t2=graham(p2,cnt2,ch2);
            if(C_S(ch1,t1,ch2,t2)&&C_S(ch2,t2,ch1,t1)) printf("Successful!
    ");  
            else printf("Infinite loop!
    ");  
        }
    }
  • 相关阅读:
    python 列表与字符串互相转化
    python爬虫——BeautifulSoup详解(附加css选择器)
    python——requests库
    用代理池 + redis 刷博客浏览量(2)
    scrapy爬取知乎用户信息并存入mongodb
    python 爬虫 计算博客园浏览量,刷浏览量(1)
    python SocketServer模块创建TCP服务器·
    【XSY1986】【BZOJ1455】罗马游戏
    【模板】左偏树
    CF464D World of Darkraft
  • 原文地址:https://www.cnblogs.com/isakovsky/p/11247373.html
Copyright © 2011-2022 走看看