HDU5299 圆的扫描线 && 树上删边博弈
HDU5299 圆的扫描线 && 树上删边博弈
标签(空格分隔): 未分类
给出若干个圆,可以互相嵌套但不相交或相切。
每次删去一个圆和它内部的圆,进行博弈,问谁赢。
分成两部分。首先我们要处理出给定圆的嵌套关系,然后解决博弈问题。
首先保证圆不相交切不相切的话,所有圆之间的关系形成一堆树。
那么这个问题转化为树上每次删除一个边和它的子树,删不了为输,问谁赢。
树上删边问题:每个儿子的\(sg\)为1,\(一个节点的sg=所有儿子节点的\)(sg+1)\(的异或和\)。
重点是怎么处理不相交圆的嵌套关系
这要用到圆的扫描线。
所有对不相交圆的的处理都可以用扫描线。
类似于hdu3511. hdu3511是让你求嵌套层数最深的一个圆,和这个题是一样的。
首先对于所有圆,一个圆创建两个事件点,一个进一个出。对所有时间点排序,按照x从小到大。
然后逐个处理事件点,用一个set维护所有圆。每当遇到一个进入事件,分四种情况讨论这个圆的位置关系,然后把这个圆插入set中。每当遇到一个离开事件,从set中删除这个圆。
set中圆的排序方法是按照当前扫描线所在的位置和圆的交点进行排序的。这里由于圆没有相交,所以交点的高低顺序不变,所以可以在\(opetator <\)中动态计算交点然后比较。
圆的四种情况:(引用自这里)
- 没有上方事件点,或者没有下方事件点。这时该圆C是最外层的一个圆。
- 上方事件点和下方事件点属于同一个圆A,这时圆A必定是圆C的父亲。
- 上方事件点和下方事件点分别属于两个圆A,B,且fa(A)!=fa(B),如果fa(A)==B,那么A和C都是B的孩子。
- 上方事件点和下方事件点分别属于两个圆A,B,且fa(A)==fa(B),那么A和B都是C的兄弟。
注意为了方便最好在最外面套一个无限大的圆,避免第一种情况写出来出问题。
//扫描线
#define out (-1)
#define in (1)
#define UP (1)
#define DOWN (-1)
#define eps 1e-6
using namespace std;
int nowx;//扫描线的位置
struct circle{
int x,y,r;
circle(int x=0,int y=0,int r=0):x(x),y(y),r(r) {}
void read(){cin>>x>>y>>r;}
}c[MAXN];
struct event{
int x,type,ss;
event(int x=0,int type=0,int ss=0):x(x),type(type),ss(ss) {}
}eve[MAXN];
bool operator < (const event&a,const event &b){
if (a.x==b.x){
if (a.type==b.type) return a.ss<b.ss;
else return a.type>b.type;
}
else return a.x<b.x;
}
struct node{
int ss,type;
node(int ss=0,int type=0):ss(ss),type(type) {}
};
double get_pos(const node &p){
int type=p.type , ss=p.ss;
if(type==UP) return (double)c[ss].y+sqrt((double)c[ss].r*c[ss].r-(double)(c[ss].x-nowx)*(c[ss].x-nowx));
if(type==DOWN) return (double)c[ss].y-sqrt((double)c[ss].r*c[ss].r-(double)(c[ss].x-nowx)*(c[ss].x-nowx));
}
bool operator < (const node &a,const node &b){
double A=get_pos(a),B=get_pos(b);
return A > B || fabs(A-B)<eps && a.type > b.type;
}
bool operator == (const node &a,const node &b){return a.ss==b.ss && a.type==b.type;}
set<node> s;
typedef set<node>::iterator it;
int fa[MAXN];
int main (int argc, char *argv[])
{
int n;
cin>>n;
int cnt=1;
FOR(i,1,n){
c[i].read();
eve[cnt++]=event(c[i].x-c[i].r,in,i);
eve[cnt++]=event(c[i].x+c[i].r,out,i);
}
sort(eve+1,eve+cnt);
FOR(i,1,cnt-1){
int ss=eve[i].ss;
nowx=eve[i].x;//移动扫描线到当前位置
if (eve[i].type==in){
it up=s.lower_bound(node(ss,UP));
it down=s.upper_bound(node(ss,UP));
//这里没有在最外层套一个大圆
if (up==s.begin() || down==s.end()){//情况1
fa[ss]=0;
s.insert(node(ss,UP));
s.insert(node(ss,DOWN));
continue;
}
--up;
if (up->ss==down->ss){//情况2
fa[ss]=up->ss;
}else if (fa[up->ss]!=fa[down->ss]){//情况3
if (fa[up->ss]==down->ss) fa[ss]=down->ss;
else if (fa[down->ss]==up->ss) fa[ss]=up->ss;
}else{//情况4
fa[ss]=fa[up->ss];
}
s.insert(node(ss,UP));
s.insert(node(ss,DOWN));
}else{
s.erase(node(ss,UP));
s.erase(node(ss,DOWN));
}
}
return 0;
}
HDU5299 圆的扫描线 && 树上删边博弈的更多相关文章
- 【HDU 3590】 PP and QQ (博弈-Anti-SG游戏,SJ定理,树上删边游戏)
PP and QQ Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- 【BZOJ 2688】 2688: Green Hackenbush (概率DP+博弈-树上删边)
2688: Green Hackenbush Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 42 Solved: 16 Description ...
- HDU 5299 圆扫描线 + 树上删边
几何+博弈的简单组合技 给出n个圆,有包含关系,以这个关系做游戏,每次操作可以选择把一个圆及它内部的圆全部删除,不能操作者输. 圆的包含关系显然可以看做是树型结构,所以也就是树上删边的游戏. 而找圆的 ...
- POJ Christmas Game [树上删边游戏 Multi-SG]
传送门 题意: 有N 个局部联通的图.Harry 和Sally 轮流从图中删边,删去一条边后,不与根节点相连的部分将被移走.Sally 为先手.图是通过从基础树中加一些边得到的.所有形成的环保证不共用 ...
- POJ.3710.Christmas Game(博弈论 树上删边游戏 Multi-SG)
题目链接 \(Description\) 给定n棵"树",每棵"树"的节点可能"挂着"一个环,保证没有环相交,且与树只有一个公共点. 两人轮 ...
- POJ 3710 无向图简单环树上删边
结论题,这题关键在于如何转换环,可以用tarjan求出连通分量后再进行标记,也可以DFS直接找到环后把点的SG值变掉就行了 /** @Date : 2017-10-23 19:47:47 * @Fil ...
- HDU 1524 树上无环博弈 暴力SG
一个拓扑结构的图,给定n个棋的位置,每次可以沿边走,不能操作者输. 已经给出了拓扑图了,对于每个棋子找一遍SG最后SG和就行了. /** @Date : 2017-10-13 20:08:45 * @ ...
- HDU 3094 树上删边 NIM变形
基本的树上删边游戏 写过很多遍了 /** @Date : 2017-10-13 18:19:37 * @FileName: HDU 3094 树上删边 NIM变形.cpp * @Platform: W ...
- hdu3511 Prison Break 圆的扫描线
地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=3511 题目: Prison Break Time Limit: 10000/5000 MS ( ...
随机推荐
- Flask之flask-migrate
简介 flask-migrate是flask的一个扩展模块,主要是扩展数据库表结构的. 官方文档:http://flask-migrate.readthedocs.io/en/latest/ 使用fl ...
- Flask上下文管理
一.一些python的知识 1.偏函数 def add(x, y, z): print(x + y + z) # 原本的写法:x,y,z可以传任意数字 add(1,2,3) # 如果我要实现一个功能, ...
- Java 输入/输出流
1. 编码问题 在介绍输入输出之前我们先介绍下关于编码的一些基本知识点.当一个文件里既有中文字符又有英文字符时.他们在不同的编码方式下会占领不同的内存: 1. ANSI 中文占领 2 个字节的内存空间 ...
- mysql 迁移数据
一.导出导入所有数据库的数据 1.导出 mysqldump -u root -p123456 --all-databases > all.sql 2.导入 mysql -u root -p123 ...
- 0602-Zuul构建API Gateway-Zuul Http Client、cookie、header
一.Zuul Http Client zuul使用的默认HTTP客户端现在由Apache HTTP Client支持,而不是已弃用的Ribbon RestClient.要使用RestClient或使用 ...
- 在firefox安装Selenium IDE
1.打开地址:https://addons.mozilla.org/en-US/firefox/addon/selenium-ide/: 2.点击Add to Firefox: 3.打开Firefox ...
- golang在线手册汇总
1. golang官网 https://golang.org/ 2. golang中国 http://www.golangtc.com/ http://godoc.golangtc.com/pkg/ ...
- Yii 2.x 和1.x区别以及yii2.0安装
知乎上有个类似的问题:http://www.zhihu.com/question/22924271/answer/23085751 大致思路不会变,开发流程变化也不是很大.有变化的是1.yii2带入的 ...
- iOS学习之Objective-C 2.0 运行时系统编程
0 导言 本主主要内容包括: 1.概述2.参考3.运行时系统的版本和平台4.和运行时系统的交互5.消息6.动态方法解析7.消息转发8.类型编码9.属性声明 1 概述 Objective-C语言将决定尽 ...
- linux用户 群组权限
用户及passwd文件 /etc/passwd文件的功能 /etc/passwd文件每个字段的具体含义 shadow文件 /etc/shadow文件的功能 /etc/shadow文件每个字段的具体含义 ...