hihocoder 1582 : Territorial Dispute (计算几何)(2017 北京网络赛E)

题目链接

题意:给出n个点。用两种颜色来给每个点染色。问能否存在一种染色方式,使不同颜色的点不能被划分到一条直线的两侧。

题解:求个凸包(其实只考虑四个点就行。但因为有板子,所以感觉这样写更休闲一些。)。如果不是所有点都在凸包上,那么把凸包上的点染成颜色1,内部的点染成颜色2;如果是所有点都在凸包上,且点数>3,那么将第一个和第三个点染成颜色1,其余点染成颜色2;否则,不存在满足要求的染色方式。

虽然很弱但是拿到一个一血还是非常开心的~

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const LL eps=1e-10;
const LL pi=acos(-1.0);

int dcmp(LL x)
{
    if(x==0LL) return 0;
    else return x<0? -1:1;
}

struct Point
{
    LL x,y;
    int id;
    void read()
    {
        scanf("%lld%lld",&x,&y);
    }
    void output()
    {
        printf("%lld %lld
",x,y);
    }
    Point(LL x_=0,LL y_=0)
    {
        x=x_,y=y_;
    }
    Point operator -(const Point& rhs)
    {
        return Point(x-rhs.x,y-rhs.y);
    }
    Point operator +(const Point& rhs)
    {
        return Point(x+rhs.x,y+rhs.y);
    }
    Point operator *(const LL& t)
    {
        return Point(x*t,y*t);
    }
    Point operator /(const LL& t)
    {
        return Point(x/t,y/t);
    }
    bool operator ==(const Point& rhs)
    {
        return dcmp(x-rhs.x)==0&&dcmp(y-rhs.y)==0;
    }
    bool operator<(const Point& rhs)const
    {
        return x<rhs.x||x==rhs.x&&y<rhs.y;
    }
};
typedef Point Vector;

LL Cross(Vector A,Vector B)
{
    return A.x*B.y-A.y*B.x;
}

LL Dot(Vector A,Vector B)
{
    return A.x*B.x+A.y*B.y;
}

LL Area2(Point A,Point B,Point C)
{
    return Cross(B-A,C-A);
}

bool SegmentProperIntersection(Point A1,Point B1,Point A2,Point B2)
{
    LL c1=Cross(B1-A1,A2-A1),c2=Cross(B1-A1,B2-A1),
           c3=Cross(B2-A2,A1-A2),c4=Cross(B2-A2,B1-A2);
    return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
}

bool OnSegment1(Point P,Point A,Point B)
{
    return dcmp(Cross(P-A,P-B))==0 && dcmp(Dot(P-A,P-B))<=0;
}

bool SegmentIntersection(Point A1,Point B1,Point A2,Point B2)
{
    return SegmentProperIntersection(A1,B1,A2,B2) ||
            OnSegment1(A2,A1,B1)||OnSegment1(B2,A1,B1) ||
            OnSegment1(A1,A2,B2)||OnSegment1(B1,A2,B2);
}

int ConvexHull(Point *p,int n,Point *ch)
{
    sort(p,p+n);
    int m=0;
    for(int i=0; i<n; ++i)
    {
        while(m>1&&dcmp(Area2(ch[m-2],ch[m-1],p[i]))<=0) --m;    //直到 ch[m-2],ch[m-1],p[i] 不是顺时针且不在同一直线 
        ch[m++]=p[i];
    }
    int k=m;
    for (int i=n-2; i>=0; --i)
    {
        while(m>k&&dcmp(Area2(ch[m-2],ch[m-1],p[i]))<=0) --m;
        ch[m++]=p[i];
    }
    return n>1?m-1:m;
}

//==============================================

int n,nc;
Point p[105],ch[105];
int c[105];

bool ok()
{
    nc=ConvexHull(p,n,ch);
    if(nc<n)
    {
        for(int i=0;i<nc;i++)
            c[ch[i].id]=1;
        return true;
    }
    else if(nc>3)
    {
        c[ch[0].id]=1;
        c[ch[2].id]=1;
        return true;
    }
    else 
        return false;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        memset(c,0,n*sizeof(int));
        for(int i=0;i<n;i++)
            p[i].read(),p[i].id=i;
        if(ok())
        {
            puts("YES");
            for(int i=0;i<n;i++)
                printf("%c",c[i]?'A':'B');
            puts("");
        }
        else
            puts("NO");
    }
}
原文地址:https://www.cnblogs.com/Just--Do--It/p/7582228.html