把每个人的监视范围看成点,相邻的两个监视范围连边,那么跑一遍最短路就可以了(事实上边权都为1可以直接bfs)。显然存在最优路线没有某个时刻同时被多于两人监视,要到达另一个区域的话完全可以经过分界线而不是和其他区域的交点(若两个区域只有一个交点的话是不能直接到达的),总之就是说不用特判同时被多人监视的情况。

  现在问题是怎么求出哪些监视范围相邻。考虑对于某个人的监视范围求出所有与它相邻的。两个监视范围的公共边是这两个人连线的中垂线,把这些线画出来可以发现求个半平面交就好了。注意线要求在矩形范围内。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 610
#define vector dot
int T,n,p[N],d[N],queue[N],cnt;
bool flag[N];
const double eps=1E-;
struct data{int to,nxt;
}edge[N*N];
struct dot
{
double x,y;
vector operator +(const vector&a) const
{
return (vector){x+a.x,y+a.y};
}
vector operator -(const vector&a) const
{
return (vector){x-a.x,y-a.y};
}
double operator *(const vector&a) const
{
return x*a.y-y*a.x;
}
vector operator *(const double a) const
{
return (vector){a*x,a*y};
}
double len()
{
return sqrt(x*x+y*y);
}
vector rotate()
{
return (vector){-y,x};
}
}a[N],P[N];
struct line
{
dot a;vector p;int i;
bool operator <(const line&a) const
{
return atan2(p.x,p.y)>atan2(a.p.x,a.p.y);
}
}q[N],Q[N];
void addedge(int x,int y){cnt++;edge[cnt].to=y,edge[cnt].nxt=p[x],p[x]=cnt;}
bool onright(line x,dot y)
{
return (y-x.a)*x.p>=;
}
dot cross(line x,line y)
{
return y.a+y.p*(x.p*(x.a-y.a)/(x.p*y.p));
}
int bfs(int S)
{
memset(d,,sizeof(d));
int head=,tail=;queue[]=S;d[S]=;
do
{
int x=queue[++head];
for (int i=p[x];i;i=edge[i].nxt)
if (d[x]+<d[edge[i].to])
{
d[edge[i].to]=d[x]+;
queue[++tail]=edge[i].to;
if (!edge[i].to) return d[edge[i].to];
}
}while (head<tail);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("3297.in","r",stdin);
freopen("3297.out","w",stdout);
const char LL[]="%I64d";
#else
const char LL[]="%lld";
#endif
T=read();
while (T--)
{
n=read();
int r=read(),c=read();
dot s;s.x=read(),s.y=read();
for (int i=;i<=n;i++)
a[i].x=read(),a[i].y=read();
int S;
double dis=(a[]-s).len();
for (int i=;i<=n;i++) dis=min(dis,(a[i]-s).len());
for (int i=;i<=n;i++) if (fabs(dis-(a[i]-s).len())<eps) S=i;
cnt=;
memset(p,,sizeof(p));
for (int j=;j<=n;j++)
{
int t=;
for (int i=;i<=n;i++)
if (i!=j) q[++t]=(line){(a[i]+a[j])*0.5,(a[i]-a[j]).rotate(),i};
q[++t]=(line){(dot){,},(vector){,},};
q[++t]=(line){(dot){r,},(vector){,},};
q[++t]=(line){(dot){r,c},(vector){-,},};
q[++t]=(line){(dot){,c},(vector){,-},};
sort(q+,q+t+);
int head=,tail=;Q[]=q[];
for (int i=;i<=t;i++)
{
while (head<tail&&onright(q[i],P[tail])) tail--;
while (head<tail&&onright(q[i],P[head+])) head++;
Q[++tail]=q[i];
if (fabs(Q[tail-].p*Q[tail].p)<eps)
{
tail--;
if (onright(q[i],Q[tail].a)) Q[tail]=q[i];
}
if (head<tail) P[tail]=cross(Q[tail],Q[tail-]);
}
while (head<tail&&onright(Q[head],P[tail])) tail--;
P[head]=cross(Q[head],Q[tail]);
for (int i=head;i<=tail;i++) addedge(j,Q[i].i);
}
printf("%d\n",bfs(S));
}
return ;
}

Luogu3297 SDOI2013逃考(半平面交+最短路)的更多相关文章

  1. BZOJ3199 SDOI2013 逃考 半平面交、最短路

    传送门 如果我们对于每一个点能找到与其相邻的点(即不经过其他点监视范围能够直接到达其监视范围的点)和是否直接到达边界,就可以直接BFS求最短路求出答案. 所以当前最重要的问题是如何找到对于每一个点相邻 ...

  2. 洛谷 P3297 [SDOI2013]逃考 解题报告

    P3297 [SDOI2013]逃考 题意 给一个平面矩形,里面有一些有标号点,有一个是人物点,人物点会被最近的其他点控制,人物点要走出矩形,求人物点最少被几个点控制过. 保证一开始只被一个点控制,没 ...

  3. luogu P3297 [SDOI2013]逃考

    传送门 gugugu 首先每个人管理的区域是一个多边形,并且整个矩形是被这样的多边形填满的.现在的问题是求一条经过多边形最少的路径到达边界,这个可以最短路. 现在的问题是建图,显然我们应该给相邻的多边 ...

  4. P3297 [SDOI2013]逃考

    传送门 完全看不出这思路是怎么来的-- 首先对于两个亲戚,他们监视范围的边界是他们连线的中垂线.那么对于一个亲戚来说它能监视的范围就是所有的中垂线形成的半平面交 然后如果某两个亲戚的监视范围有公共边, ...

  5. [JZOJ3297] 【SDOI2013】逃考

    题目 我发现我现在连题面都懒得复制粘贴了-- 题目大意 在一个矩形中有一堆点,这堆点按照以下规则将矩形瓜分成一堆块: 对于每个坐标,它属于离它最近的点的块. 一个人从某个坐标出发到矩形外面,求经过的最 ...

  6. 【JZOJ3297】【SDOI2013】逃考(escape)

    Mission 高考又来了,对于不认真读书的来讲真不是个好消息.为了小杨能在家里认真读书,他的亲戚决定驻扎在他的家里监督他学习,有爷爷奶奶.外公外婆.大舅.大嫂.阿姨-- 小杨实在是忍无可忍了,这种生 ...

  7. 2018.10.15 bzoj4445: [Scoi2015]小凸想跑步(半平面交)

    传送门 话说去年的省选计算几何难度跟前几年比起来根本不能做啊(虽然去年考的时候并没有学过计算几何) 这题就是推个式子然后上半平面交就做完了. 什么? 怎么推式子? 先把题目的概率转换成求出可行区域. ...

  8. 【POJ 3525】Most Distant Point from the Sea(直线平移、半平面交)

    按逆时针顺序给出n个点,求它们组成的多边形的最大内切圆半径. 二分这个半径,将所有直线向多边形中心平移r距离,如果半平面交不存在那么r大了,否则r小了. 平移直线就是对于向量ab,因为是逆时针的,向中 ...

  9. 【BZOJ-2618】凸多边形 计算几何 + 半平面交 + 增量法 + 三角剖分

    2618: [Cqoi2006]凸多边形 Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 959  Solved: 489[Submit][Status] ...

随机推荐

  1. HNOI2016做题笔记

    HNOI2016 最小公倍数 (分块.并查集) 看到这种不能用数据结构(实际上是可以用K-D Tree的)维护的题目就应该想到分块然后使用并查集维护连通性和一个连通块中的\(maxa , maxb\) ...

  2. sqlserver 隔离级别 - 转

    SQL-92标准中定义了四个隔离级别,这四个隔离级别在以前版本的SQL Server中即受到支持: READ UNCOMMITTED READ UNCOMMITTED是限制性最弱的隔离级别,因为该级别 ...

  3. Kafka:Configured broker.id 2 doesn't match stored broker.id 0 in meta.properties.

    在安装Kafka集群的时候,碰到这个问题. 我们知道在搭建Kafka集群的时候,我们需要设置broker.id,以作为当前服务器在整个集群的唯一标志. 网上搜查资料是说,log.dirs目录下的met ...

  4. 2011 noip 提高组

    首先吐槽:刚刚写着写着突然蓝屏了,,emmm,写到最后一题了蓝屏了. 当时我的内心是崩溃的. 然后,旁边的大佬默默来了一句:论保存草稿的重要性. 连着蓝了三次之后开了防火墙,然后,,我左边那位同学又开 ...

  5. 使用Pyspark进行特征工程时的那些坑

    以脚本spark_clean_online_action.py.数据集new_sxf_time_count_1781115582.csv为例: 集群节点包括212.216.217.218.需要注意的是 ...

  6. Appium Studio 初体验(windows做ios自动化,录制appium脚本)

    偶然的机会遇到了这个工具——Appium Studio, 在官网是这么解释的 Get your Appium testing projects going within minutesInstall ...

  7. Ionic 入门与实战之第一章:Ionic 介绍与相关学习资源

    原文发表于我的技术博客 本文是「Ionic 入门与实战」系列连载的第一章,主要对 Ionic 的概念.发展历程.适配的移动平台等知识进行了介绍,并分享了 Ionic 相关的学习资源. 原文发表于我的技 ...

  8. CrackMe-005全破详解(图文+源码)--上篇

    逆向破解 | 逆向 | 逆向分析 | CrackMe | Crack | CrackMe5 | CrackMe05 前言 CrackMe005,都说比较变态,很多人给放过去了,但是我还是决定上了它,既 ...

  9. 图像数据增强 (Data Augmentation in Computer Vision)

    1.1 简介 深层神经网络一般都需要大量的训练数据才能获得比较理想的结果.在数据量有限的情况下,可以通过数据增强(Data Augmentation)来增加训练样本的多样性, 提高模型鲁棒性,避免过拟 ...

  10. Python_函数的镶嵌和作用域链_26

    def max(a,b): return a if a>b else b def the_max(x,y,z): #函数的嵌套调用 c = max(x,y) return max(c,z) pr ...