2017icpc北京賽區網絡賽E題(計算幾何)

時間限制: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.

樣例輸入
2
2
0 0
0 1
4
0 0
0 1
1 0
1 1
樣例輸出
NO
YES

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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章