首页 > 代码库 > 计数方法,博弈论(扫描线,树形SG):HDU 5299 Circles Game

计数方法,博弈论(扫描线,树形SG):HDU 5299 Circles Game

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
  这道题目可以说是模板题……
  就是那个SG函数的求法貌似是结论,我不会证明。
 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cmath>
 6 #include <set>
 7 using namespace std;
 8 const int N=20010,M=40010;
 9 int cnt,fir[N],to[N],nxt[N];
10 void addedge(int a,int b){
11     nxt[++cnt]=fir[a];
12     to[fir[a]=cnt]=b;
13 }
14 int sqr(int x){return x*x;}
15 int tmp;
16 struct Circle{
17     int x,y,r;
18     Circle(int _=0,int __=0,int ___=0){x=_;y=__;r=___;}
19 }c[N];
20 
21 struct Point{
22     int x,id,tp;
23     Point(int _=0,int __=0,int ___=0){x=_;id=__;tp=___;}
24     friend bool operator<(Point a,Point b){
25         double x=c[a.id].y+a.tp*sqrt(sqr(c[a.id].r)-sqr(tmp-c[a.id].x));
26         double y=c[b.id].y+b.tp*sqrt(sqr(c[b.id].r)-sqr(tmp-c[b.id].x));
27         if(x!=y)return x<y;return a.tp<b.tp;
28     } 
29 }st[M];
30 
31 bool cmp(Point a,Point b){return a.x<b.x;}
32 set<Point>s;set<Point>::iterator it;
33 
34 int fa[N],sg[N];
35 int DFS(int x){
36     sg[x]=0;
37     for(int i=fir[x];i;i=nxt[i])
38         sg[x]^=DFS(to[i])+1;
39     return sg[x];
40 }
41 
42 void Init(){
43     memset(fir,0,sizeof(fir));
44     cnt=0;
45 }
46 int T,n;
47 int main(){
48     scanf("%d",&T);
49     while(T--){
50         Init();scanf("%d",&n);
51         for(int i=1;i<=n;i++){
52             scanf("%d%d%d",&c[i].x,&c[i].y,&c[i].r);
53             st[2*i-1]=Point(c[i].x-c[i].r,i,-1);
54             st[2*i]=Point(c[i].x+c[i].r,i,1);
55         }
56         sort(st+1,st+2*n+1,cmp);
57         for(int i=1;i<=2*n;i++){
58             Point x=st[i];tmp=x.x;
59             if(x.tp==-1){
60                 it=s.upper_bound(Point(0,x.id,1));
61                 if(it==s.end())addedge(fa[x.id]=0,x.id);
62                 else{
63                     Point y=*it;
64                     if(y.tp==1)
65                         addedge(fa[x.id]=y.id,x.id);
66                     else
67                         addedge(fa[x.id]=fa[y.id],x.id);
68                 }
69                 s.insert(Point(0,x.id,1));
70                 s.insert(Point(0,x.id,-1));
71             }
72             else{
73                 s.erase(Point(0,x.id,1));
74                 s.erase(Point(0,x.id,-1));
75             }
76         }
77         printf(DFS(0)?"Alice\n":"Bob\n");    
78     }
79     return 0;
80 }

 

计数方法,博弈论(扫描线,树形SG):HDU 5299 Circles Game