hdu5299 Circles Game

来源:互联网 发布:碳基生物知乎 编辑:程序博客网 时间:2024/05/19 02:25

Circles Game

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1427    Accepted Submission(s): 451


Problem Description
There are n circles on a infinitely large table.With every two circle, either one contains another or isolates from the other.They are never crossed nor tangent.
Alice and Bob are playing a game concerning these circles.They take turn to play,Alice goes first:
1、Pick out a certain circle A,then delete A and every circle that is inside of A.
2、Failling to find a deletable circle within one round will lost the game.
Now,Alice and Bob are both smart guys,who will win the game,output the winner's name.
 

Input
The first line include a positive integer T<=20,indicating the total group number of the statistic.
As for the following T groups of statistic,the first line of every group must include a positive integer n to define the number of the circles.
And the following lines,each line consists of 3 integers x,y and r,stating the coordinate of the circle center and radius of the circle respectively.
n≤20000,|x|≤20000,|y|≤20000,r≤20000。
 

Output
If Alice won,output “Alice”,else output “Bob”
 

Sample Input
210 0 16-100 0 90-50 0 1-20 0 1100 0 9047 0 123 0 1
 

Sample Output
AliceBob
 

Author
FZUACM
 

Source
2015 Multi-University Training Contest 1



显然圆的包含关系可以构成一片森林,然后问题就可以转化为:每一步可以删除森林的一棵树或者某树的一棵子树,不能删者输。这样,问题就变成经典的树上删边游戏了。

树上删边游戏有一个很重要的结论:叶子节点的SG值为0,中间节点的SG值为它的所有子节点的SG值加1后的异或和。(证明详见贾志豪论文《组合游戏略述——浅谈SG游戏的若干拓展及变形》)

现在,我们的主要问题就是如何把圆的包含关系转化为森林。这里要用到圆的扫描线算法。首先对于每个圆,创建两个时间点,一个进入一个离开,再对所有时间点从小到大排序。然后逐个处理时间点,用set维护所有圆,每遇到一个进入时间,分情况讨论圆的位置关系,然后把这个圆插入set中。每遇到一个离开时间,从set中删除这个圆。




#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<cstdlib>#include<algorithm>#include<set>#define F(i,j,n) for(int i=j;i<=n;i++)#define D(i,j,n) for(int i=j;i>=n;i--)#define ll long long#define maxn 20010using namespace std;int t,n,cnt,tt,tmp;int head[maxn],fa[maxn];struct cir{int x,y,r;}a[maxn];struct edge_type{int next,to;}e[maxn*2];struct bor{int x,f,id;friend bool operator < (bor a,bor b){if (a.x==b.x) return a.f<b.f;return a.x<b.x;}}q[maxn*2];double get_h(int id,int x,int opt){return a[id].y+opt*sqrt(a[id].r*a[id].r-(a[id].x-x)*(a[id].x-x));}struct pos{int id,opt;pos(int a=0,int b=0){id=a;opt=b;}friend bool operator < (pos a,pos b){if (a.id==b.id) return a.opt<b.opt;return get_h(a.id,tmp,a.opt)<get_h(b.id,tmp,b.opt);}};set<pos> s;set<pos>::iterator it;inline int read(){int x=0,f=1;char ch=getchar();while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}inline void add_edge(int x,int y){e[++cnt]=(edge_type){head[x],y};head[x]=cnt;fa[y]=x;}inline ll get(int x){ll ret=0;for(int i=head[x];i;i=e[i].next) ret^=get(e[i].to);return ret+1;}int main(){t=read();while (t--){cnt=tt=0;memset(fa,0,sizeof(fa));memset(head,0,sizeof(head));n=read();F(i,1,n){a[i].x=read();a[i].y=read();a[i].r=read();q[++tt]=(bor){a[i].x-a[i].r,1,i};q[++tt]=(bor){a[i].x+a[i].r,-1,i};}sort(q+1,q+tt+1);F(i,1,tt){if (q[i].f==1){tmp=q[i].x;it=s.lower_bound(pos(q[i].id,1));if (it!=s.end()){if (it->opt==1) add_edge(it->id,q[i].id);else if (fa[it->id]) add_edge(fa[it->id],q[i].id);}s.insert(pos(q[i].id,1));s.insert(pos(q[i].id,-1));}else{s.erase(pos(q[i].id,1));s.erase(pos(q[i].id,-1));}}ll sum=0;F(i,1,n) if (!fa[i]) sum=sum^get(i);puts(sum?"Alice":"Bob");}}


1 0
原创粉丝点击