HDU 5299 Circles Game (圆的扫描线+树上SG)

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5299


题意:

平面上有n个两两不交的圆,现在有两个人轮流选取圆,每选到一个圆就要把这个圆及其内部的所有圆都删去,最后不能操作的人输,问谁有必胜策略。


分析:

由于圆两两不交,如果根据圆的包含关系建个图,可以得到一个森林,问题转化为树上的SG博弈,复杂度O(nlogn),

建图的时候需要用到圆的扫描线,具体可以搜索HDU3511 Prison Break的题解,

有关树上SG博弈的结论可以参看2009年国家集训队贾志豪的论文《组合游戏略述——浅谈SG游戏的若干拓展及变形》。


代码:

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef double db;
const db eps=1e-6;
const int MAXN=20005;
int sgn(db x)
{
    if(x>eps)return 1;
    if(x<-eps)return -1;
    return 0;
}
db Time;
struct Circle
{
    db x,y,r;
    db getX(int flag)
    {
        return x-flag*r;
    }
    db getY(int flag)
    {
        return y+flag*sqrt(max(r*r-(Time-x)*(Time-x),0.0));
    }
}c[MAXN];
struct Event
{
    db x,y;
    int v,id;
    bool operator < (const Event &t)const
    {
        return sgn(x-t.x)==0 ? ve[MAXN];
int p[MAXN],dep[MAXN];
struct node
{
    int id,flag;
    node(){}
    node(int _id,int _flag):id(_id),flag(_flag){}
    bool operator < (const node &t)const
    {
        db y1=c[id].getY(flag);
        db y2=c[t.id].getY(t.flag);
        return sgn(y1-y2)==0 ? flagLine;
    set::iterator up,down;
    for(int i=1;i<=2*n;i++)
    {
        Time=s[i].x;
        if(s[i].v<0)
        {
            Line.erase(node(s[i].id,1));
            Line.erase(node(s[i].id,-1));
        }
        else
        {
            down=Line.lower_bound(node(s[i].id,1));
            up=down;
            if(down==Line.begin() || up==Line.end())
            {
                e[0].push_back(s[i].id);
                p[s[i].id]=0;
                dep[s[i].id]=1;
            }
            else if((--down)->id == up->id)
            {
                e[down->id].push_back(s[i].id);
                p[s[i].id]=down->id;
                dep[s[i].id]=dep[down->id]+1;
            }
            else
            {
                if(dep[down->id] > dep[up->id])
                {
                    e[up->id].push_back(s[i].id);
                    p[s[i].id]=up->id;
                    dep[s[i].id]=dep[up->id]+1;
                }
                else if(dep[up->id] > dep[down->id])
                {
                    e[down->id].push_back(s[i].id);
                    p[s[i].id]=down->id;
                    dep[s[i].id]=dep[down->id]+1;
                }
                else
                {
                    e[p[down->id]].push_back(s[i].id);
                    p[s[i].id]=p[down->id];
                    dep[s[i].id]=dep[p[down->id]]+1;
                }
            }
            Line.insert(node(s[i].id,1));
            Line.insert(node(s[i].id,-1));
        }
    }
}
int dfs(int u)
{
    int res=0;
    for(int i=0;i


你可能感兴趣的:(ACM,-,数据结构,ACM,-,计算几何,ACM,-,组合数学)