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
- HDU 5299 Circles Game (圆的扫描线+树上SG)
- hdu 5299 Circles Game 2015 Multi-University Training Contest 1 计算几何+博弈SG函数 圆的扫描线
- HDOJ 5299 Circles Game 圆嵌套+树上SG
- 【HDU5299】Circles Game,圆的扫描线+树上删边游戏
- hdu 5299(树上删边游戏) Circles Game
- HDU 5299 Circles Game
- HDU 5299 Circles Game
- hdu 5299 Circles Game
- HDU 5299 Circles Game
- hdu 5299 Circles Game
- HDU 5299 Circles Game(树的删边游戏)
- HDU 5299 Circles Game(树&博弈)
- hdu 5299 Circles Game(博弈)
- hdu 5299——Circles Game
- 组合游戏(Circles Game,HDU 5299)
- [多校2015.01.1012 博弈] hdu 5299 Circles Game
- hdu 5299 Circles Game 2015 Multi-University Training Contest 1
- hdu Stone Game SG函数
- Android应用的自动升级、更新模块的实现完整方案+参考程序
- hdu5392
- 经典SQL语句集锦
- 笔试题:在一个字符串中查找子字符串的个数
- R语言之多元回归实战
- HDU 5299 Circles Game (圆的扫描线+树上SG)
- Robotium 自动化测试
- Java访问控制符:public,private,protected
- ZOJ 3702 Gibonacci number
- IOS navigationItem 设置返回按钮,title图片和rightBarButtonItem
- LDF文件过大,如何收缩
- uva 111 History Grading
- Web系统大规模并发——电商秒杀与抢购
- Algorithms—120.Triangle