传送门


如果我们对于每一个点能找到与其相邻的点(即不经过其他点监视范围能够直接到达其监视范围的点)和是否直接到达边界,就可以直接BFS求最短路求出答案。

所以当前最重要的问题是如何找到对于每一个点相邻的点。

如果你知道泰森多边形,你就可以发现所有点的监视范围刚好对应这些点在这个矩形里的泰森多边形。

因为两个点监视范围的分界线一定在这两个点对应线段的中垂线上,所以将当前点到所有点的中垂线拿出来跑一遍半平面交,如果某个点与当前点的中垂线在半平面交中,那么这两个点就相邻。

还需要知道对于某个点能否不经过其他点的监视范围到达边界,这只需要在求半平面交的时候将矩形的四边也加上就可以了。

时间复杂度\(O(TN^2logN)\),可能需要轻微的常数优化。

写计算几何的时候务必注意细节,否则可能因为把\(xy\)坐标打反等小错误调很久QAQ

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
//This code is written by Itst
using namespace std; #define ld long double
const ld eps = 1e-12;
bool cmp(ld a , ld b){return a - eps < b && a + eps > b;} struct comp{
ld x , y , dir;
comp(ld _x = 0 , ld _y = 0) : x(_x) , y(_y){dir = atan2(y , x);}
comp operator +(comp a){return comp(x + a.x , y + a.y);}
comp operator -(comp a){return comp(x - a.x , y - a.y);}
comp operator *(ld a){return comp(x * a , y * a);}
ld operator *(comp a){return x * a.x + y * a.y;}
ld operator %(comp a){return x * a.y - y * a.x;}
bool operator <(const comp a)const{return dir < a.dir;}
bool operator ==(const comp a)const{return cmp(dir , a.dir);}
}now[607]; struct line{
comp pos , dir;
int ind;
line(comp a = comp(0,0) , comp b = comp(0,0) , int id = 0) : pos(a) , dir(b) , ind(id){}
bool operator <(const line a)const{return dir < a.dir || dir == a.dir && ((comp)a.pos - pos) % dir > 0;}
}cur[607]; struct Edge{
int end , upEd;
}Ed[370007];
int head[607] , que[607];
int cntEd , N , X0 , Y0 , X1 , Y1 , hd , tl , T;
bool mrk[607] , vis[607]; inline void addEd(int a , int b){
Ed[++cntEd] = (Edge){b , head[a]};
head[a] = cntEd;
} comp rot(comp a){
ld Cos = 0 , Sin = 1;
return comp(a.x * Cos - a.y * Sin , a.x * Sin + a.y * Cos);
} comp intersect(line a , line b){
ld t = (b.dir % (a.pos - b.pos)) / (a.dir % b.dir);
return a.pos + a.dir * t;
} bool chk(line a , line b , line c){
return (intersect(a , b) - c.pos) % c.dir > 0;
} void create(int x){
int cnt = 0;
cur[++cnt] = line(comp(0 , 0) , comp(1 , 0));
cur[++cnt] = line(comp(X1 , 0) , comp(0 , 1));
cur[++cnt] = line(comp(X1 , Y1) , comp(-1 , 0));
cur[++cnt] = line(comp(0 , Y1) , comp(0 , -1));
for(int i = 1 ; i <= N ; ++i)
if(i != x)
cur[++cnt] = line((now[i] + now[x]) * 0.5 , rot(now[i] - now[x]) , i);
sort(cur + 1 , cur + cnt + 1);
hd = tl = que[1] = 1;
for(int i = 2 ; i <= cnt ; ++i){
if(cur[i].dir == cur[i - 1].dir) continue;
while(hd < tl && chk(cur[que[tl]] , cur[que[tl - 1]] , cur[i]))
--tl;
while(hd < tl && chk(cur[que[hd]] , cur[que[hd + 1]] , cur[i]))
++hd;
que[++tl] = i;
}
while(hd < tl && chk(cur[que[tl]] , cur[que[tl - 1]] , cur[que[hd]]))
--tl;
while(hd <= tl){
if(!cur[que[hd]].ind) mrk[x] = 1;
else addEd(cur[que[hd]].ind , x);
++hd;
}
} int main(){
#ifndef ONLINE_JUDGE
freopen("in","r",stdin);
//freopen("out","w",stdout);
#endif
ios::sync_with_stdio(0);
for(cin >> T ; T ; --T){
cntEd = 0;
memset(mrk , 0 , sizeof(mrk));
memset(vis , 0 , sizeof(vis));
memset(head , 0 , sizeof(head));
cin >> N >> X1 >> Y1 >> X0 >> Y0;
if(!N){cout << "0\n"; continue;}
for(int i = 1 ; i <= N ; ++i)
cin >> now[i].x >> now[i].y;
for(int i = 1 ; i <= N ; ++i)
create(i);
queue < int > q;
ld minDis = 1e18;
int minInd = 0;
for(int i = 1 ; i <= N ; ++i){
ld dis = sqrt((now[i].x - X0) * (now[i].x - X0) + (now[i].y - Y0) * (now[i].y - Y0));
if(dis < minDis){minDis = dis; minInd = i;}
}
vis[minInd] = 1;
q.push(minInd);
bool f = 0;
for(int i = 1 ; !f ; ++i){
for(int j = q.size() ; !f && j ; --j){
int t = q.front(); q.pop();
if(mrk[t]){f = 1; continue;}
for(int i = head[t] ; i ; i = Ed[i].upEd)
if(!vis[Ed[i].end]){
vis[Ed[i].end] = 1;
q.push(Ed[i].end);
}
}
if(f) cout << i << endl;
}
}
return 0;
}

BZOJ3199 SDOI2013 逃考 半平面交、最短路的更多相关文章

  1. [BZOJ3199][SDOI2013]escape:半平面交

    分析 好像叫V图什么的. 容易发现,对于每个点,其监视的范围就是这个点与其它所有点的垂直平分线分割平面后的半平面交.由于数据范围很小,所以我们可以直接枚举每个点,使用双端队列求出其监视的范围.若两个点 ...

  2. Luogu3297 SDOI2013逃考(半平面交+最短路)

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

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

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

  4. 【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交

    4515: [Sdoi2016]游戏 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 129[Submit][Status][ ...

  5. poj3335 半平面交

    题意:给出一多边形.判断多边形是否存在一点,使得多边形边界上的所有点都能看见该点. sol:在纸上随手画画就可以找出规律:按逆时针顺序连接所有点.然后找出这些line的半平面交. 题中给出的点已经按顺 ...

  6. POJ3525 半平面交

    题意:求某凸多边形内部离边界最远的点到边界的距离 首先介绍半平面.半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围.如图所示: 半平面交:多个半平面的交集.有点类似 ...

  7. POJ 3130 How I Mathematician Wonder What You Are! /POJ 3335 Rotating Scoreboard 初涉半平面交

    题意:逆时针给出N个点,求这个多边形是否有核. 思路:半平面交求多边形是否有核.模板题. 定义: 多边形核:多边形的核可以只是一个点,一条直线,但大多数情况下是一个区域(如果是一个区域则必为 ).核内 ...

  8. bzoj2618[Cqoi2006]凸多边形 半平面交

    这是一道半平面交的裸题,第一次写半平面交,就说一说我对半平面交的理解吧. 所谓半平面交,就是求一大堆二元一次不等式的交集,而每个二元一次不等式的解集都可以看成是在一条直线的上方或下方,联系直线的标准方 ...

  9. POJ 3384 Feng Shui 半平面交

    题目大意:一个人很信"Feng Shui",他要在房间里放两个圆形的地毯. 这两个地毯之间可以重叠,可是不能折叠,也不能伸到房间的外面.求这两个地毯可以覆盖的最大范围.并输出这两个 ...

随机推荐

  1. Android udp json+数组 --->bytes发送数据

    Android  json支持五种数据类型 String / int(float)/bool / null  / object 今天说 object  : json = new JSONObject( ...

  2. ERP结账不自动清台的解决办法

    1. 2. 完成以上设置即可

  3. ugui SetParent在安卓上一个诡异bug

    问题描述 我的环境:Unity3D 5.3.7 出问题机型:安卓模拟器.部分低配安卓机型(比如:红米2A) 以下代码是设置某个节点的父节点,在PC.Editor.大部分手机上都是正常的,但问题机型上, ...

  4. 利用系统函数模拟实现nginx 系统脚本启动的特殊颜色专业效果

    利用系统函数模拟实现nginx 系统脚本启动的特殊颜色专业效果/etc/init.d/nginxd {start/stop/restart/reload}利用if语句实现: ============= ...

  5. PE 添加系统管理员账号(域控可加)转

    使用U盘制作一个PE系统,这里推荐老毛桃或者大白菜:开机进入Bios,选择U盘启动:进入U盘启动画面后,选择一个PE系统:进入PE系统后,我们去本机系统盘,将 C:/Windows/System32/ ...

  6. PHP下载网页

    <?php /*   author:whq   作用:获取网页的内容 */   include "../Snoopy/Snoopy.class.php";class Cute ...

  7. Linux 小知识翻译 - 「邮件服务器」

    这次聊聊「邮件服务器」. 邮件服务器上通常会运行2个服务端软件,「SMTP服务器」和「POP服务器或者IMAP服务器」. 这2个东西,也许使用邮件客户端的人立马就明白了.因为设置邮件客户端的时候,需要 ...

  8. C#基础知识之泛型集合转换为DataTable

    在做项目中,遇到了将集合转换为DataTable的使用,在网上看了资料,在这里记录下来,分享. using System; using System.Collections.Generic; usin ...

  9. Why do Kafka consumers connect to zookeeper, and producers get metadata from brokers?

    Why do Kafka consumers connect to zookeeper, and producers get metadata from brokers? Ask Question u ...

  10. B - 畅通工程再续 最小生成树

    相信大家都听说一个“百岛湖”的地方吧,百岛湖的居民生活在不同的小岛中,当他们想去其他的小岛时都要通过划小船来实现.现在政府决定大力发展百岛湖,发展首先要解决的问题当然是交通问题,政府决定实现百岛湖的全 ...