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

来源:互联网 发布:linux du显示行号 编辑:程序博客网 时间:2024/06/05 20:17

题目链接:

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


题意:

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


分析:

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

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

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


代码:

#include<cstdio>#include<cstring>#include<cstdlib>#include<cmath>#include<iostream>#include<algorithm>#include<vector>#include<set>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 ? v<t.v : x<t.x;    }}s[MAXN<<1];vector<int>e[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 ? flag<t.flag : y1<y2;    }};void build(int n){    memset(dep,0,sizeof(dep));    for(int i=0;i<=n;i++)e[i].clear();    for(int i=1;i<=n;i++)    {        s[2*i-1].x=c[i].x-c[i].r;        s[2*i-1].v=1;        s[2*i].x=c[i].x+c[i].r;        s[2*i].v=-1;        s[2*i-1].y=s[2*i].y=c[i].y;        s[2*i-1].id=s[2*i].id=i;    }    sort(s+1,s+2*n+1);    set<node>Line;    set<node>::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<e[u].size();i++)        res^=dfs(e[u][i]);    return res+(u!=0);}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        for(int i=1;i<=n;i++)            scanf("%lf%lf%lf",&c[i].x,&c[i].y,&c[i].r);        build(n);        if(dfs(0))printf("Alice\n");        else printf("Bob\n");    }    return 0;}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 有家人进了传销怎么办 有亲人进了传销怎么办 误入传销违法了怎么办 tt游戏账号忘了怎么办 被臭蚊子咬了怎么办 狗狗鼻子掉皮了怎么办 火碱弄到皮肤上怎么办 蓝斑马鱼怀孕后怎么办 汽油喝到肚子里怎么办 加了不好的汽油怎么办 不小心喝了汽油怎么办 如果误喝了汽油怎么办 小孩误喝了汽油怎么办 欠债活不下去了怎么办 待产住院住早了怎么办 狗狗一天吃一顿怎么办 四个月宝宝消化不好怎么办 内火旺盛长痘怎么办 我有恋爱恐惧症怎么办 白鹤芋叶子蔫了怎么办 白掌叶子蔫了怎么办 鱼塘的鱼不吃食怎么办 新买的鱼不吃食怎么办 养的鱼不吃食怎么办 罗汉掉鳞还是洞怎么办 刚买的鱼不吃食怎么办 锦鲤鱼掉鱼鳞片怎么办 锦鲤鱼身上烂了怎么办 鱼掉了一片鳞是怎么办 地图鱼身上烂了怎么办 小腿上有鱼鳞皮怎么办 食道里长了息肉怎么办 蟒蛇皮包翘皮了怎么办 金鱼的鱼鳞掉了怎么办 2次胎停的我该怎么办 文玩核桃尖摔了怎么办 手上长了个囊肿怎么办 腿上皮肤像鱼鳞怎么办 身上的皮肤像蛇皮鱼鳞怎么办 冬天腿上皮肤干怎么办 平板电脑白屏了怎么办