Circles Game
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1990 Accepted Submission(s): 652
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
2 1 0 0 1 6 -100 0 90 -50 0 1 -20 0 1 100 0 90 47 0 1 23 0 1
Sample Output
Alice Bob
题意:
平面中有n个圆,对于任意两个圆只有可能相离或者内含(不包括重合),现在Alice(先手)和Bob玩游戏,每个人当前可以选择一个圆,并且将这个圆及其所包含的圆全部删去,删完者胜,问极其聪明的情况下谁必胜(T组测试数据)
思路:
先新建一个无穷大的圆,之后建图:如果圆y在圆x内部,那么x向y连一条有向边,这样可以得到一棵根节点为那个无穷大的圆的树,这样问题就转变成了:给你一棵树,两个玩家每次可以选择一条边将这条边从树上断开,谁操作完后只剩下根节点谁胜
这是经典的树上删边博弈(参考:《组合游戏略述--浅谈SG游戏的若干拓展及变形》)
可以得出结论:所有叶子节点SG为0,非叶子节点的SG为所有儿子的SG值+1的异或,最后看根SG值是否为0即可
然后如何建图:这是一个经典的圆扫描线:https://blog.csdn.net/Jaihk662/article/details/78556857
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<map>
#include<set>
#include<string>
#include<math.h>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
#define LL long long
#define mod 1000000007
typedef struct Circle
{
int x, y, r, t, id, val;
bool operator < (const Circle &b) const
{
if(x<b.x || x==b.x && t<b.t || x==b.x && t==b.t && r>b.r)
return 1;
return 0;
}
}Circle;
Circle s[400005], c[200005], temp;
typedef struct Pset
{
int id, t;
bool operator < (const Pset &b) const
{
if(id==0)
return 1;
else if(b.id==0)
return 0;
else if(id==b.id)
{
if(t>b.t)
return 1;
return 0;
}
else
{
double p1, p2;
p1 = c[id].y+t*sqrtl((LL)c[id].r*c[id].r-(LL)(temp.x-c[id].x)*(temp.x-c[id].x));
p2 = c[b.id].y+b.t*sqrtl((LL)c[b.id].r*c[b.id].r-(LL)(temp.x-c[b.id].x)*(temp.x-c[b.id].x));
if(p1>p2)
return 1;
return 0;
}
}
}Pset;
Pset now, it;
set<Pset> st;
vector<int> G[200005];
int fa[200005];
int Sech(int u)
{
int i, v, now;
now = 0;
for(i=0;i<G[u].size();i++)
{
v = G[u][i];
//printf("%d %d\n", u, v);
now ^= Sech(v)+1;
}
return now;
}
int main(void)
{
int cnt, T, n, i;
scanf("%d", &T);
while(T--)
{
cnt = 0;
scanf("%d", &n);
for(i=0;i<=n;i++)
G[i].clear();
for(i=1;i<=n;i++)
{
scanf("%d%d%d", &c[i].x, &c[i].y, &c[i].r);
s[++cnt].x = c[i].x-c[i].r, s[cnt].y = c[i].y, s[cnt].t = 1, s[cnt].id = i, s[cnt].r = c[i].r;
s[++cnt].x = c[i].x+c[i].r, s[cnt].y = c[i].y, s[cnt].t = -1, s[cnt].id = i, s[cnt].r = c[i].r;
}
sort(s+1, s+cnt+1);
now.id = 0, now.t = 1;
st.insert(now);
for(i=1;i<=cnt;i++)
{
if(s[i].t==1)
{
temp = s[i];
now.id = s[i].id;
now.t = 1;
it = *(--st.upper_bound(now));
if(it.t==1)
{
G[it.id].push_back(now.id);
fa[now.id] = it.id;
}
else
{
G[fa[it.id]].push_back(now.id);
fa[now.id] = fa[it.id];
}
st.insert(now);
now.t = -1;
st.insert(now);
}
else
{
now.id = s[i].id;
now.t = 1;
st.erase(now);
now.t = -1;
st.erase(now);
}
}
st.clear();
if(Sech(0)==0)
printf("Bob\n");
else
printf("Alice\n");
}
return 0;
}
/*
2
1
0 0 1
6
-100 0 90
-50 0 1
-20 0 1
100 0 90
47 0 1
23 0 1
*/