计算几何叉乘二分+博弈

Problem G

Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 65536/65536K (Java/Other)
Total Submission(s) : 34   Accepted Submission(s) : 15

Font: Times New Roman | Verdana | Georgia

Font Size: ← →

Problem Description

Recently, Lur have a good luck. He is also the cleverest boy in his school as he create the most popular computer game – Lucky Boy. The game is played by two players, a and b, in 2d planar .In the game Lucky Boy, there are n different points on plane, each time one can remove one or multiple co-line points from the plane. The one who can firstly remove more than two points from the plane wins. The one who removes the last point on the plane can also win the game. You may assume that two players are both clever enough that they can always make the best choice. The winner is called Lucky Boy.
Given the n points, can you tell me who will be the Lucky Boy ? Note that player a will always the first one to remove points from the plane.

Input

The first line of each case is an integer n(03), following n lines each contains two integers x and y(0<=x, y<=10 8), describing the coordinates of each point. Ended by EOF.

Output

Output “a is the lucky boy.” in a single line if a win the game, otherwise you should output “b is the lucky boy.” in a single line.

Sample Input

3
0 0
1 1
2 2
3
0 0
1 1
2 3

Sample Output

a is the lucky boy.
b is the lucky boy.

在二维空间中有n个点,如果n个点中存在三点共线的情况,则 a 胜(Lucky Boy);如果n个点中不存在三点共线的情况,那么从平面上擦除最后一个点的玩家胜。

数据规模:n<=1000。

极角排序,二分出来两条向量叉乘为0的点,n*n*logn

简单取牌1张or2张博弈

#define DeBUG
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std ;
#define zero {0}
#define INF 0x3f3f3f3f
#define EPS 1e-6
typedef long long LL;
const double PI = acos(-1.0);
//#pragma comment(linker, "/STACK:102400000,102400000")
inline int sgn(double x)
{
    return fabs(x) < EPS ? 0 : (x < 0 ? -1 : 1);
}
#define N 1005
struct Point;
typedef Point Vec;
struct Point
{
    double x, y;
    Point () {}
    Point(double a, double b)
    {
        x = a;
        y = b;
    }
};

Vec operator + (const Vec &a, const Vec &b) //点加法
{
    return Vec(a.x + b.x, a.y + b.y);
}
Vec operator - (const Vec &a, const Vec &b) //点减法
{
    return Vec(a.x - b.x, a.y - b.y);
}
inline double crossDet(Vec a, Vec b)//叉乘
{
    return a.x * b.y - a.y * b.x;
}
Point origin;
bool cmp3(const Point &a, const Point &b)
{
    int ret = crossDet(a - origin , b - origin );
    if (ret > 0)
        return true;
    return false;
}
Point p[N];
int main()
{
#ifdef DeBUGs
    freopen("C:\\Users\\Sky\\Desktop\\1.in", "r", stdin);
#endif
    int n;
    origin = Point(0, 0);
    while (scanf("%d", &n) + 1)
    {
        for (int i = 0; i < n; i++)
        {
            scanf("%lf%lf", &p[i].x, &p[i].y);
        }
        Vec a, b;
        sort(p, p + n, cmp3);
        int flag = 0;
        int l, r, mid;
        for (int i = 0; i < n - 2; i++)
        {
            for (int j = i + 1; j < n - 1; j++)
            {
                a = p[j] - p[i];
                l = j + 1;
                r = n - 1;
                while (l <= r)
                {
                    mid = (l + r) >> 1;
                    b = p[mid] - p[i];
                    if (sgn(crossDet(a, b)) < 0)
                        l = mid + 1;
                    else if (sgn(crossDet(a, b)) == 0)
                    {
                        flag = 1;
                        goto set;
                    }
                    else
                        r = mid - 1;
                }
            }
        }
set:    if (flag)
        {
            printf("a");
        }
        else
        {
            if (n % 3 == 0)
            {
                printf("b");
            }
            else
            {
                printf("a");
            }
        }
        printf(" is the lucky boy.\n");
    }

    return 0;
}




你可能感兴趣的:(ACM-计算几何)