2017icpc北京赛区网络赛E题(计算几何)

来源:互联网 发布:虚拟机上安装linux 编辑:程序博客网 时间:2024/06/05 10:10
时间限制:1000ms
单点时限:1000ms
内存限制:256MB

描述

In 2333, the C++ Empire and the Java Republic become the most powerful country in the world. They compete with each other in the colonizing the Mars.

There are n colonies on the Mars, numbered from 1 to n. The i-th colony's location is given by a pair of integers (xi, yi). Notice that latest technology in 2333 finds out that the surface of Mars is a two-dimensional plane, and each colony can be regarded as a point on this plane. Each colony will be allocated to one of the two countries during the Mars Development Summit which will be held in the next month.

After all colonies are allocated, two countries must decide a border line. The Mars Development Convention of 2048 had declared that: A valid border line of two countries should be a straight line, which makes colonies of different countries be situated on different sides of the line.

The evil Python programmer, David, notices that there may exist a plan of allocating colonies, which makes the valid border line do not exist. According to human history, this will cause a territorial dispute, and eventually lead to war.

David wants to change the colony allocation plan secretly during the Mars Development Summit. Now he needs you to give him a specific plan of allocation which will cause a territorial dispute. He promises that he will give you 1000000007 bitcoins for the plan.

输入

The first line of the input is an integer T, the number of the test cases (T ≤ 50).

For each test case, the first line contains one integer n (1 ≤ n ≤ 100), the number of colonies.

Then n lines follow. Each line contains two integers xi, yi (0 ≤ xi, yi ≤ 1000), meaning the location of the i-th colony. There are no two colonies share the same location.

There are no more than 10 test cases with n > 10.

输出

For each test case, if there exists a plan of allocation meet David's demand, print "YES" (without quotation) in the first line, and in the next line, print a string consisting of English letters "A" and "B". The i-th character is "A" indicates that the i-th colony was allocated to C++ Empire, and "B" indicates the Java Republic.

If there are several possible solutions, you could print just one of them.

If there is no solution, print "NO".

注意

This problem is special judged.

样例输入
220 00 140 00 11 01 1
样例输出
NOYES

ABBA


解题思路:对于n为1, 2, 3特判一下就行,n大于等于4是一定有解,所有从n个点中任意取4个,关键在于怎样给这四个点染色(其余点任意),分两种情况,一种是可以从这四个点中找出两条线段,这两条线段相交,那么我们其中一条线段染成一种颜色,另外的一条线段染成另一种颜色就行,第二种情况是这四个点中找不出两条线段相交,那么这是我们判断有没有一点在另外三个点组成的三角形内就行, 这个里面的点染成一种颜色,其他染成别的颜色就行。

#include<stdio.h>#include<iostream>#include<cmath>#include<algorithm>#include<cstring>using namespace std;const long double eps = 1e-10;struct Point{    long double x, y;    Point(long double _x = 0, long double _y = 0){        x = _x;        y = _y;    }};typedef Point Vector;Vector operator +(Vector A, Vector B) {return Vector(A.x + B.x, A.y + B.y);}//向量加Vector operator -(Vector A, Vector B) {return Vector(A.x - B.x, A.y - B.y);}//向量减Vector operator *(Vector A, long double p) {return Vector(p * A.x, p * A.y);}//向量的数乘Vector operator /(Vector A, long double p) {return Vector(A.x / p, A.y / p);}//向量的数除Vector operator -(Vector A) {return Vector(-A.x, -A.y);}//向量的取反int dcmp(long double x){    if(fabs(x) < eps) return 0;    else return x < 0 ? -1 : 1;}bool operator == (const Point& a, const Point& b) {    return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;}long double Cross(Vector A, Vector B)//求解向量叉积{    return A.x * B.y - A.y * B.x;}long double Dot(Vector A, Vector B)//求解向量数量积{    return A.x * B.x + A.y * B.y;}long double xmulti(Point p, Point a, Point b)//求向量pa叉乘pb{    return (a.x - p.x) * (b.y - p.y) - (a.y - p.y) * (b.x - p.x);}struct Line{    Point p1;    Point p2;    Line(Point _p1, Point _p2){        p1 = _p1;        p2 = _p2;    }    Line(){        p1 = Point(0, 0);        p2 = Point(0, 0);    }};typedef Line seg;bool judge(Line l1, Line l2)//线段l2与直线l1是否相交{    Point p1 = l1.p1;    Point p2 = l1.p2;    Point p3 = l2.p1;    Point p4 = l2.p2;    Vector V1 = Vector(p2.x - p1.x, p2.y - p1.y);    Vector V2 = Vector(p3.x - p1.x, p3.y - p1.y);    Vector V3 = Vector(p4.x - p1.x, p4.y - p1.y);    long double C1 = Cross(V2, V1);    long double C2 = Cross(V3, V1);    if(dcmp(C1) * dcmp(C2) <= 0) return true;    else return false;}int line_loc(Line l1, Line l2)//判断直线的位置关系,1为平行,0为重合,-1为相交{    Point p1 = l1.p1;    Point p2 = l1.p2;    Point p3 = l2.p1;    Point p4 = l2.p2;    Vector v1 = p2 - p1;    Vector v2 = p4 - p3;    Vector v3 = p3 - p1;    long double d1 = Cross(v1, v2);    long double d2 = Cross(v1, v3);    if(dcmp(d1) == 0 && dcmp(d2) == 0) return 0;//重合    else if(dcmp(d1) == 0) return 1;    else return -1;}bool seg_seg(Line l1, Line l2)//线段l1与线段l2是否相交{     if(line_loc(l1, l2) == 0)     {         long double l = l1.p1.x;         long double r = l1.p2.x;         if(dcmp(l - r) > 0) swap(l, r);         long double jju1 = l2.p1.x;         long double jju2 = l2.p2.x;         if(dcmp(jju1 - l) * dcmp(jju1 - r) <= 0) return true;         if(dcmp(jju2 - l) * dcmp(jju2 - r) <= 0) return true;         return false;     }     if(judge(l1, l2) && judge(l2, l1)) return true;     else return false;}bool point_line(Point p1, Point p2, Point p3)//判断p1, p2. p3三点是否共线{    Vector V1 = Vector(p2.x - p1.x, p2.y - p1.y);    Vector V2 = Vector(p3.x - p1.x, p3.y - p1.y);    long double jud = Cross(V1, V2);    if(dcmp(jud) == 0) return true;    else return false;}Point seg_intersecting(Line l1, Line l2)//求两相交的直线(线段也一样)的交点{    Point A = l1.p1;    Point B = l1.p2;    Point C = l2.p1;    Point D = l2.p2;    long double _x, _y;    _x = (xmulti(A, B, D) * C.x - xmulti(A, B, C) * D.x) / (xmulti(A, B, D) - xmulti(A, B, C));    _y = (xmulti(A, B, D) * C.y - xmulti(A, B, C) * D.y) / (xmulti(A, B, D) - xmulti(A, B, C));    return Point(_x, _y);}bool tri_in(Point p1, Point p2, Point p3, Point p4)//判断p4,是否在p1, p2, p3组成的三角形里面{    Line l1, l2, l3;    l1.p1 = p1;    l1.p2 = p2;    l2.p1 = p2;    l2.p2 = p3;    l3.p1 = p1;    l3.p2 = p3;    Line test;    test.p1 = p4;    test.p2 = Point(-1000000000000, p4.y);    int se = 0;    Point see[3];    if(seg_seg(l1, test)) see[++se] = seg_intersecting(l1, test);    if(seg_seg(l2, test)) see[++se] = seg_intersecting(l2, test);    if(seg_seg(l3, test)) see[++se] = seg_intersecting(l3, test);    //cout<<"se == "<<se<<endl;    if(se == 1) return true;    if(se == 2)    {        if(see[1] == see[2]) return true;        else return false;    }    else return false;}int n;Point pp[200];bool visit[200];bool ans;void init(){    ans = false;    memset(visit, false, sizeof(visit));}struct node{    int id;    long double x;}Node[10];bool cmp(node n1, node n2){    return n1.x < n2.x;}int main(){    int T;    scanf("%d", &T);    while(T--)    {        scanf("%d", &n);        init();        for(int i = 1; i <= n; i++)        {            cin>>pp[i].x>>pp[i].y;        }        if(n == 1 || n == 2)        {            printf("NO\n");            continue;        }        if(n == 3)        {            if(!point_line(pp[1], pp[2], pp[3]))            {                printf("NO\n");                continue;            }            else            {                Vector v1 = Vector(pp[2].x - pp[1].x, pp[2].y - pp[1].y);                Vector v2 = Vector(pp[3].x - pp[1].x, pp[3].y - pp[1].y);                long double value1 = Dot(v1, v2);                if(dcmp(value1) < 0)                {                    visit[1] = true;                }                v1 = Vector(pp[1].x - pp[2].x, pp[1].y - pp[2].y);                v2 = Vector(pp[3].x - pp[2].x, pp[3].y - pp[2].y);                value1 = Dot(v1, v2);                if(dcmp(value1) < 0)                {                    visit[2] = true;                }                v1 = Vector(pp[1].x - pp[3].x, pp[1].y - pp[3].y);                v2 = Vector(pp[2].x - pp[3].x, pp[2].y - pp[3].y);                value1 = Dot(v1, v2);                if(dcmp(value1) < 0)                {                    visit[3] = true;                }                printf("YES\n");                for(int j = 1; j <= n; j++)                {                    if(visit[j]) cout<<"A";                    else cout<<"B";                }                cout<<endl;                continue;            }        }        for(int i = 1; i <= n; i++)        {            for(int j = i + 1; j <= n; j++)            {                for(int k = j + 1; k <= n; k++)                {                    for(int m = k + 1; m <= n; m++)                    {                        Point p1 = pp[i];                        Point p2 = pp[j];                        Point p3 = pp[k];                        Point p4 = pp[m];                        Line l1 = Line(p1, p2);                        Line l2 = Line(p3, p4);                        if(seg_seg(l1, l2))                        {                            ans = true;                            visit[i] = true;                            visit[j] = true;                            break;                        }                        l1 = Line(p1, p3);                        l2 = Line(p2, p4);                        if(seg_seg(l1, l2))                        {                            ans = true;                            visit[i] = true;                            visit[k] = true;                            break;                        }                        l1 = Line(p1, p4);                        l2 = Line(p2, p3);                        if(seg_seg(l1, l2))                        {                            ans = true;                            visit[i] = true;                            visit[m] = true;                            break;                        }                        if(tri_in(p1, p2, p3, p4))                        {                            visit[m] = true;                            ans = true;                            break;                        }                        if(tri_in(p4, p2, p3, p1))                        {                            visit[i] = true;                            ans = true;                            break;                        }                        if(tri_in(p4, p1, p3, p2))                        {                            visit[j] = true;                            ans = true;                            break;                        }                        if(tri_in(p1, p2, p4, p3))                        {                            visit[k] = true;                            ans = true;                            break;                        }                    }                    if(ans) break;                }                if(ans) break;            }            if(ans) break;        }        if(ans)        {            printf("YES\n");            for(int i = 1; i <= n; i++)            {                if(visit[i]) cout<<"A";                else cout<<"B";            }            cout<<endl;        }        else cout<<"NO"<<endl;    }    return 0;}


阅读全文
0 0