hihoCoder #1582 Territorial Dispute 几何凸包

hihoCoder #1582  Territorial Dispute

题意:给出 n 个点,染两种颜色,问是否有一种染色方案,使得没有任何一条直线可以划分开这两种颜色的点。

tags:求个凸包,如果内部有点就内部点染一种颜色,如果内部没点就凸包上的点交替染。 还有 n==3 且在一条直线上的情况,特判一下。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi  first
#define se  second
typedef long long ll;
const double eps=1e-8;
const int N = 200005;

struct Point { double x, y; int id; } p[N], sta[N];
int isZero(double x) {      //x是否为0
    return (x>0 ? x : -x) < eps;
}
double crossProd(Point A,Point B,Point C) {     //叉积,这样写即A->B到A->C逆时针为正
    return (B.x-A.x)*(C.y-A.y)-(B.y-A.y)*(C.x-A.x);
}
double Dis(Point A,Point B) {
    return sqrt((B.x-A.x)*(B.x-A.x)+(B.y-A.y)*(B.y-A.y));
}
//以最左下的点为基准点,其他各点(逆时针方向)以极角从小到大的排序规则
bool cmp(Point a, Point b)
{
    double tmp = crossProd(p[1], a, b);    //极角大小转化为求叉乘
    if(tmp>0 || (isZero(tmp)&&Dis(p[1],a)<Dis(p[1],b))) return 1;
    else return 0;
}
int top;
void Graham(int _n)
{
    int mi=1;
    double mx=p[1].x, my=p[1].y;
    for(int i=2; i<=_n; ++i)    //找到最左下点
        if(my>p[i].y || my==p[i].y&&mx>p[i].x)
            mi=i, my=p[i].y, mx=p[i].x;
    swap(p[1], p[mi]);  //最左下点要换到p开头,不能让它和它自己比
    sort(p+2, p+1+_n, cmp);
    sta[1]=p[1], sta[2]=p[2], sta[3]=p[3];
    p[_n+1]=p[1];    //在结尾加最左下点为结束点
    top=2;
    for(int i=3; i<=_n+1; i++) {
        //加入一个点后,向右偏拐或共线,则上一个点不在凸包内,则--top,该过程直到不向右偏拐或没有三点共线的点
        while(crossProd(sta[top-1],sta[top],p[i])<0 && top) top--;
        sta[++top]=p[i];
    }
}

int n;
bool ans[N];
int main()
{
    int T;  scanf("%d", &T);
    while(T--)
    {
        mes(ans, false);
        scanf("%d", &n);
        rep(i,1,n)
            scanf("%lf%lf", &p[i].x, &p[i].y),  p[i].id=i;
        if(n<3) { puts("NO");  continue; }
        if(n==3 && (p[1].y-p[2].y)*(p[2].x-p[3].x) != (p[2].y-p[3].y)*(p[1].x-p[2].x) ) {
            puts("NO");  continue;
        }
        puts("YES");
        Graham(n);
        --top;
        if(top<n)
        {
            rep(i,1,top) ans[sta[i].id]=true;
        }
        else
        {
            rep(i,1,top) if(i&1) ans[sta[i].id]=true;
        }
        rep(i,1,n)
            printf("%c", ans[i] ? 'A' : 'B');
        puts("");
    }

    return 0;
}
原文地址:https://www.cnblogs.com/sbfhy/p/7606476.html