把每个人的监视范围看成点,相邻的两个监视范围连边,那么跑一遍最短路就可以了(事实上边权都为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. Ionic 图片延时加载

    图片的延时加载是为了提供App的运行效率,那么是如何实现的呢?献上github:  https://github.com/paveisistemas/ionic-image-lazy-load 1.下 ...

  2. 性能调优之vmstat命令

    vmstat是Virtual Meomory Statistics(虚拟内存统计)的缩写,可对操作系统的虚拟内存.进程.IO读写.CPU活动等进行监视.它是对系统的整体情况进行统计,不足之处是无法对某 ...

  3. IO复用\阻塞IO\非阻塞IO\同步IO\异步IO

    转载:IO复用\阻塞IO\非阻塞IO\同步IO\异步IO 一. 什么是IO复用? 它是内核提供的一种同时监控多个文件描述符状态改变的一种能力:例如当进程需要操作多个IO相关描述符时(例如服务器程序要同 ...

  4. 七年一冠、IG牛13的背后是什么!

    最近忙着看S8世界总决赛,博客荒废了近一个月,后续步入正轨.   2018年11月3日.S8世界总决赛.中国终于夺得了S系列赛的总冠军. “IG牛逼”也开始刷爆社交圈,对于在S3入坑的我来说,也弥补上 ...

  5. C# 爬虫 正则、NSoup、HtmlAgilityPack、Jumony四种方式抓取小说

    心血来潮,想爬点小说.通过百度选择了个小说网站,随便找了一本小说http://www.23us.so/files/article/html/13/13655/index.html. 1.分析html规 ...

  6. 《坦克世界》1.0+:使用 CPU 优化的图形和物理丰富用户体验

    本文以<坦克世界>为例,介绍 Wargaming 使用 CPU 多核和 CPU 单指令多数据 (SIMD) 功能显著提升游戏沉浸式体验的创新方法.我们以英特尔® 线程构建模块(英特尔® T ...

  7. Session会话与Cookie简单说明

    会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...

  8. C_数据结构_递归实现累加

    # include <stdio.h> long sum(int n) { //用递归实现: ) ; else ) + n; /* 用for循环实现: long s = 0; int i; ...

  9. 20135323符运锦----LINUX第三次实践:程序破解

    程序破解 一.掌握NOP.JNE.JE.JMP.CMP汇编指令的机器码 ①NOP:NOP指令即"空指令".执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行N ...

  10. UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现(转)

    UML图中类之间的关系:依赖,泛化,关联,聚合,组合,实现   类与类图 1) 类(Class)封装了数据和行为,是面向对象的重要组成部分,它是具有相同属性.操作.关系的对象集合的总称. 2) 在系统 ...