把每个人的监视范围看成点,相邻的两个监视范围连边,那么跑一遍最短路就可以了(事实上边权都为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. linux中断源码分析 - 软中断(四)

    本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 在上一篇文章中,我们看到中断实际分为了两个部分,俗称就是一部分是硬中断,一部分是软中断.软中断是专门用于处理中断 ...

  2. 9-51单片机ESP8266学习-AT指令(单片机采集温湿度数据通过8266发送给AndroidTCP客户端显示)

    http://www.cnblogs.com/yangfengwu/p/8798512.html 补充:今天答应了一个朋友写一下如果单片机发过的是字符串应该怎么解析,答应了今天写,哦哦哦是明天了,闲话 ...

  3. 使用Topshelf管理Windows服务

    目的:以控制台方式开发Windows服务程序,调试部署方便. https://www.cnblogs.com/itjeff/p/8316244.html https://www.cnblogs.com ...

  4. Sharding模式

    将数据存储为一组水平的数据分区.这种模式可以在存储和访问大量的数据的时候提高可扩展性. 场景和问题 由单个服务器托管的数据存储可能受到下列限制: 存储空间限制.基于大规模云应用所使用的数据仓库,可能会 ...

  5. 面试3——java集合类总结(Map)

    1.概述: Java 中的map集合使用键值对(key-value)来保持数据,其中值(value)可以重复,键(key)必须唯一,但最多只能有一个key为空,它的主要实现类有HashMap.Hash ...

  6. Git push 时如何避免出现 "Merge branch 'master' of ..."

    在使用 Git 的进行代码版本控制的时候,往往会发现在 log 中出现 "Merge branch 'master' of ..." 这句话,如下图所示.日志中记录的一般为开发过程 ...

  7. Zabbix监控系统部署:配置详解

    1. 全局配置 ListenPort ,监听端口 ,取值范围为1024-32767,默认端口10051 SourceIP,外发连接源地址 LogType,日志类型:单独日志文件,系统文件,控制台输出 ...

  8. Ionic 2 官方示例程序 Super Starter

    原文发表于我的技术博客 本文分享了 Ionic 2 官方示例程序 Super Starter 的简要介绍与安装运行的方法,最好的学习示例代码,项目共包含了 14 个通用的页面设计,如:引导页.主页面详 ...

  9. 【CV】ICCV2015_Unsupervised Visual Representation Learning by Context Prediction

    Unsupervised Visual Representation Learning by Context Prediction Note here: it's a learning note on ...

  10. HTML编码规则

    <!DOCTYPE html><!-- 为每一个HTML页面的第一行添加标准模式 --> <html lang="en-us"> <!-- ...