HDU5299 圆的扫描线 && 树上删边博弈

标签(空格分隔): 未分类


给出若干个圆,可以互相嵌套但不相交或相切。

每次删去一个圆和它内部的圆,进行博弈,问谁赢。


分成两部分。首先我们要处理出给定圆的嵌套关系,然后解决博弈问题。

首先保证圆不相交切不相切的话,所有圆之间的关系形成一堆树。

那么这个问题转化为树上每次删除一个边和它的子树,删不了为输,问谁赢。


树上删边问题:每个儿子的\(sg\)为1,\(一个节点的sg=所有儿子节点的\)(sg+1)\(的异或和\)。


重点是怎么处理不相交圆的嵌套关系

这要用到圆的扫描线。

所有对不相交圆的的处理都可以用扫描线。

类似于hdu3511. hdu3511是让你求嵌套层数最深的一个圆,和这个题是一样的。

首先对于所有圆,一个圆创建两个事件点,一个进一个出。对所有时间点排序,按照x从小到大。

然后逐个处理事件点,用一个set维护所有圆。每当遇到一个进入事件,分四种情况讨论这个圆的位置关系,然后把这个圆插入set中。每当遇到一个离开事件,从set中删除这个圆。

set中圆的排序方法是按照当前扫描线所在的位置和圆的交点进行排序的。这里由于圆没有相交,所以交点的高低顺序不变,所以可以在\(opetator <\)中动态计算交点然后比较。

圆的四种情况:(引用自这里

  1. 没有上方事件点,或者没有下方事件点。这时该圆C是最外层的一个圆。
  2. 上方事件点和下方事件点属于同一个圆A,这时圆A必定是圆C的父亲。
  3. 上方事件点和下方事件点分别属于两个圆A,B,且fa(A)!=fa(B),如果fa(A)==B,那么A和C都是B的孩子。
  4. 上方事件点和下方事件点分别属于两个圆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 圆的扫描线 && 树上删边博弈的更多相关文章

  1. 【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 ...

  2. 【BZOJ 2688】 2688: Green Hackenbush (概率DP+博弈-树上删边)

    2688: Green Hackenbush Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 42  Solved: 16 Description   ...

  3. HDU 5299 圆扫描线 + 树上删边

    几何+博弈的简单组合技 给出n个圆,有包含关系,以这个关系做游戏,每次操作可以选择把一个圆及它内部的圆全部删除,不能操作者输. 圆的包含关系显然可以看做是树型结构,所以也就是树上删边的游戏. 而找圆的 ...

  4. POJ Christmas Game [树上删边游戏 Multi-SG]

    传送门 题意: 有N 个局部联通的图.Harry 和Sally 轮流从图中删边,删去一条边后,不与根节点相连的部分将被移走.Sally 为先手.图是通过从基础树中加一些边得到的.所有形成的环保证不共用 ...

  5. POJ.3710.Christmas Game(博弈论 树上删边游戏 Multi-SG)

    题目链接 \(Description\) 给定n棵"树",每棵"树"的节点可能"挂着"一个环,保证没有环相交,且与树只有一个公共点. 两人轮 ...

  6. POJ 3710 无向图简单环树上删边

    结论题,这题关键在于如何转换环,可以用tarjan求出连通分量后再进行标记,也可以DFS直接找到环后把点的SG值变掉就行了 /** @Date : 2017-10-23 19:47:47 * @Fil ...

  7. HDU 1524 树上无环博弈 暴力SG

    一个拓扑结构的图,给定n个棋的位置,每次可以沿边走,不能操作者输. 已经给出了拓扑图了,对于每个棋子找一遍SG最后SG和就行了. /** @Date : 2017-10-13 20:08:45 * @ ...

  8. HDU 3094 树上删边 NIM变形

    基本的树上删边游戏 写过很多遍了 /** @Date : 2017-10-13 18:19:37 * @FileName: HDU 3094 树上删边 NIM变形.cpp * @Platform: W ...

  9. hdu3511 Prison Break 圆的扫描线

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=3511 题目: Prison Break Time Limit: 10000/5000 MS ( ...

随机推荐

  1. 一篇搞定MongoDB

    MongoDB最基础的东西,我这边就不多说了,这提供罗兄三篇给大家热身 MongoDB初始 MongoDB逻辑与物理存储结构 MongoDB的基础操作 最后对上述内容和关系型数据做个对比 非关系型数据 ...

  2. java基础03变量和基本数据类型

    package cn.bdqn.test; /** * * @author 小豆腐 * * 变量:会变化的量?? * 一个数据在内存中存储空间的表示!在运行期间可以动态改变! * * 关键字:在jav ...

  3. 19.Delete Documents-官方文档摘录

    1 插入例子 db.inventory.insertMany( [ { item: "journal", qty: 25, size: { h: 14, w: 21, uom: & ...

  4. 内核通信之Netlink源码分析-用户内核通信原理2

    2017-07-05 上文以一个简单的案例描述了通过Netlink进行用户.内核通信的流程,本节针对流程中的各个要点进行深入分析 sock的创建 sock管理结构 sendmsg源码分析  sock的 ...

  5. 为什么使用Sails?

    http://sailsdoc.swift.ren/ 这里有 sails中文文档 http://www.jianshu.com/p/ac2da4142259 前言 入手Node.js半年,从用Expr ...

  6. Java中的编码乱码问题

    1. Eclipse的Run Configurations中,可以配置Console的Encoding Eclipse中使用 mvn clean package命令来执行. 设置为MS932时,下面的 ...

  7. thunk函数

    1.函数参数求值的策略 a.传值策略(c语言) 传值策略就是在进入函数体之前将 参数计算之后 将参数的值传入到函数体之中. let x = 8 f(x + 1)//参数为 f(9)//传进去的值实际上 ...

  8. 聚类之k-means

    1.介绍 k-means算法以k为参数(所期望的簇的个数),把n个对象分成k个簇(单层划分),用质心(数据点的平均值)定义簇的原型.使得簇内具有较高的相似度,而簇间的相似度较低. 通过聚类,我们能够发 ...

  9. POJ - 1966 Cable TV Network (最大流求点连通度)

    题意:求一个无向图的点连通度.点联通度是指,一张图最少删掉几个点使该图不连通:若本身是非连通图,则点连通度为0. 分析:无向图的点连通度可以转化为最大流解决.方法是:1.任意选择一个点作为源点:2.枚 ...

  10. 零基础学习openstack【完整中级篇】及openstack资源汇总

    1.你是如何学习openstack的?2.你对openstack的组件了解多少?3.你认为openstack该如何学习? 一直想写关于openstack的方面的内容,今天终于整理完成.算是完成一桩心事 ...