您的位置:首页 > 其它

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

2015-08-19 15:24 225 查看
题目链接:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: