1. 程式人生 > >【hiho1582】Territorial Dispute(凸包)

【hiho1582】Territorial Dispute(凸包)

題目連結

#1582 : Territorial Dispute

時間限制: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 ofdifferent 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個點,是否不能用一條直線將這些點分成兩部分,若是,則輸出YES並輸出方案,若不是,則輸出NO。

【解題思路】

顯然當n<=2時是不能的。

當n=3時,若n個點可構成直線則是可以的,比如ABA,若不能構成直線,則不行。

當n>3時,不管怎樣都是可以的,如果圍成凸包用了所有點,只需隨便挑兩個不相鄰的點填入A,其餘填入B即可。若沒有用,只需將凸包上的點填入A,凸包內的點填入B即可。

【程式碼】

#include<bits/stdc++.h>
using namespace std;
const double PI=acos(1.0);
const int maxn=1005;
int f[maxn];
struct Node
{
    int x,y;
    int num;
}node[maxn],v[maxn];
bool cmp1(Node a,Node b)
{
    return (a.y!=b.y)?a.y<b.y:a.x<b.x;
}
int cross(Node a,Node b,Node c)
{
    return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);
}
double dis(Node a,Node b)
{
    return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y)*0.1);
}
bool cmp2(Node a,Node b)
{
    int m=cross(node[1],a,b);
    if(m>0)return 1;
    else if(m==0 && dis(node[1],a)-dis(node[1],b)<=0)return 1;
    else return 0;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,x,y;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            node[i].x=x;node[i].y=y;
            node[i].num=i;
        }
        memset(v,0,sizeof(v));
        memset(f,0,sizeof(f));
        sort(node+1,node+n+1,cmp1);
        v[1]=node[1];
        sort(node+2,node+n+1,cmp2);
        v[2]=node[2];
        int top=2;
        for(int i=3;i<=n;i++)
        {
            while(top>1 && cross(v[top-1],v[top],node[i])<=0)
                top--;
            v[++top]=node[i];
        }
        //printf("%d\n",top);
        if((n==3 && top==3) || n<=2)
        {
            printf("NO\n");
            continue;
        }
        if(top==n)f[v[1].num]=1,f[v[3].num]=1;
        else
        {
            for(int i=1;i<=top;i++)
            {
                f[v[i].num]=1;
            }
        }
        printf("YES\n");
        for(int i=1;i<=n;i++)
        {
            if(f[i])printf("A");
            else printf("B");
        }
        printf("\n");
    }

}