传送门

gugugu

首先每个人管理的区域是一个多边形,并且整个矩形是被这样的多边形填满的.现在的问题是求一条经过多边形最少的路径到达边界,这个可以最短路.

现在的问题是建图,显然我们应该给相邻的多边形连边,考虑一个人和另一个人的多边形交界线,这个线就是两点线段的中垂线,于是我们可以每次把一个人所有的分界线和矩形边界拿出来求一个半平面交,如果某条边在半平面交上就和对应点连边就好了,矩形边界在半平面交上就和外面连边.最后求起点所在多边形到外面的最短路

然后我半平面交写错,就写了半天qwq

#include<bits/stdc++.h>
#define LL long long
#define db long double
#define il inline using namespace std;
const int N=600+10;
const db eps=1e-10;
il LL rd()
{
LL x=0,w=1;char ch=0;
while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*w;
}
int to[N*N],nt[N*N],hd[N],tot;
void add(int x,int y){++tot,to[tot]=y,nt[tot]=hd[x],hd[x]=tot;}
struct point
{
db x,y;
point(){}
point(db nx,db ny){x=nx,y=ny;}
point operator - (const point &bb) const {return point(x-bb.x,y-bb.y);}
db operator * (const point &bb) const {return x*bb.x+y*bb.y;}
db operator ^ (const point &bb) const {return x*bb.y-y*bb.x;}
}a[N],sht;
db sq(db x){return x*x;}
db dis(point aa,point bb){return sqrt(sq(bb.x-aa.x)+sq(bb.y-aa.y));}
db ang(point aa,point bb){return atan2((bb.y-aa.y),(bb.x-aa.x));}
struct line
{
int ii;
point x,y;
db k,b,ag;
line(){}
line(int id,point nx,point ny)
{
ii=id;
x=nx,y=ny;
k=fabs(x.x-y.x)>eps?(x.y-y.y)/(x.x-y.x):1e18;
b=k<1e17?x.y-k*x.x:x.x;
ag=ang(x,y);
}
bool operator < (const line &bb) const {return fabs(ag-bb.ag)>eps?ag<bb.ag:dis(sht,x)<dis(sht,bb.x);}
}lb[N],q[N];
point jiao(line aa,line bb)
{
db x=max(aa.k,bb.k)<1e17?(bb.b-aa.b)/(aa.k-bb.k):(aa.k>bb.k?aa.b:bb.b);
db y=aa.k<bb.k?aa.k*x+aa.b:bb.k*x+bb.b;
return point(x,y);
}
int n,tp;
int ll,rr,di[N];
bool v[N];
db mx,my,sx,sy; int main()
{
int T=rd();
while(T--)
{
memset(hd,0,sizeof(hd)),tot=0;
n=rd();
mx=rd(),my=rd(),sx=rd(),sy=rd();
for(int i=1;i<=n;++i)
{
int x=rd(),y=rd();
a[i]=point(x,y);
}
lb[0].ag=-2333;
for(int i=1;i<=n;++i)
{
sht=a[i];
int m=0;
for(int j=1;j<=n;++j)
if(i!=j)
{
point md=point((a[i].x+a[j].x)/2,(a[i].y+a[j].y)/2);
db kk=fabs(a[i].x-a[j].x)>eps?-1/((a[i].y-a[j].y)/(a[i].x-a[j].x)):0,bb=md.y-kk*md.x;
point xx=point(md.x-1,kk*(md.x-1)+bb),yy=point(md.x+1,kk*(md.x+1)+bb);
if(fabs(a[i].y-a[j].y)<eps) xx=point(md.x,md.y-1),yy=point(md.x,md.y+1);
if(((xx-a[i])^(yy-a[i]))<eps) swap(xx,yy);
lb[++m]=line(j,xx,yy);
}
lb[++m]=line(0,point(0,my),point(0,0));
lb[++m]=line(0,point(mx,my),point(0,my));
lb[++m]=line(0,point(mx,0),point(mx,my));
lb[++m]=line(0,point(0,0),point(mx,0));
sort(lb+1,lb+m+1);
int las=m;
m=0;
for(int j=1;j<=las;++j)
if(fabs(lb[j].ag-lb[j-1].ag)>eps) lb[++m]=lb[j];
ll=1,q[rr=1]=lb[1];
for(int j=2;j<=m;++j)
{
while(ll<rr&&((lb[j].y-lb[j].x)^(jiao(q[rr],q[rr-1])-lb[j].x))<eps) --rr;
while(ll<rr&&((lb[j].y-lb[j].x)^(jiao(q[ll],q[ll+1])-lb[j].x))<eps) ++ll;
q[++rr]=lb[j];
}
while(ll<rr&&((q[ll].y-q[ll].x)^(jiao(q[rr],q[rr-1])-q[ll].x))<eps) --rr;
for(int j=ll;j<=rr;++j) add(i,q[j].ii);
}
int sta=0;
db ma=1e17;
for(int i=1;i<=n;++i)
if(ma>=dis(point(sx,sy),a[i]))
ma=dis(point(sx,sy),a[i]),sta=i;
queue<int> qq;
memset(di,0x3f3f3f,sizeof(di));
di[sta]=0,v[sta]=1,qq.push(sta);
while(!qq.empty())
{
int x=qq.front();
qq.pop();
v[x]=0;
for(int i=hd[x];i;i=nt[i])
{
int y=to[i];
if(di[y]>di[x]+1)
{
di[y]=di[x]+1;
if(!v[y]) v[y]=1,qq.push(y);
}
}
}
printf("%d\n",di[0]);
}
return 0;
}

luogu P3297 [SDOI2013]逃考的更多相关文章

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

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

  2. P3297 [SDOI2013]逃考

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

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

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

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

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

  5. luogu P3305 [SDOI2013]费用流

    题目链接 bz似乎挂了... luogu P3305 [SDOI2013]费用流 题解 dalao告诉我,这题 似乎很水.... 懂了题目大意就可以随便切了 问1,最大流 问2,二分最大边权求,che ...

  6. [JZOJ3297] 【SDOI2013】逃考

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

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

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

  8. BZOJ 3203 Luogu P3299 [SDOI2013]保护出题人 (凸包、斜率优化、二分)

    惊了,我怎么这么菜啊.. 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=3203 (luogu)https://www.lu ...

  9. Luogu P3305 [SDOI2013]费用流 二分 网络流

    题目链接 \(Click\) \(Here\) 非常有趣的一个题目. 关键结论:所有的单位费用应该被分配在流量最大的边上. 即:在保证最大流的前提下,使最大流量最小.这里我们采用二分的方法,每次判断让 ...

随机推荐

  1. AITP

    AITP AITP比较简单,适合刚毕业,即将开始IT生涯的学生.接受CIPS认证课程的毕业生可以自动获得AITP证书,并获得一年的免费的CIPS会员资格. 接受非CIPS认证课程的毕业生需要申请,另外 ...

  2. JSON字符串 与 JSON对象 互转

    一,JSON字符串与JSON对象的区别 JSON对象是符合JSON格式的对象,可以用"对象.属性"进行存取值; JSON字符串是符合JSON格式的字符串; 二,JSON字符串-&g ...

  3. A1064. Complete Binary Search Tree

    A Binary Search Tree (BST) is recursively defined as a binary tree which has the following propertie ...

  4. JavaScript深入系列(一)--原型和原型链详解

    构造函数创建对象 首先我们先使用构造函数创建一个对象: function Person(){} var person = new Person(); person.name = 'tom'; cons ...

  5. (七)修改上一条SQL语句,NULL值的滤空函数nvl

    修改上一条SQL语句 1.用c命令来修改(c 即 change ) 默认,光标闪烁位置指向上一条SQL语句的第一行.输入二则定位到第二行. c /错误的关键字/正确的关键字 SQL form emp; ...

  6. vue在body上面绑定enter事件

    mounted () { this.bodyListener = (e) => { if (e.keyCode === 13 && e.target === document.b ...

  7. Hibernate 二(一级缓存,多表设计之一对多)

    1       对象状态与一级缓存 1.1   状态介绍 l  hibernate 规定三种状态:瞬时态.持久态.脱管态 l  状态 瞬时态:transient,session没有缓存对象,数据库也没 ...

  8. ajax多表单序列化

    今天在修一个后台接收参数为空值的bug 找了好久才发现原来是form表单合拼参数的时候把参数给搞没了 (我也不知道为什么啊—_—!) //对表单进行Json对象序列化 (function($){ $. ...

  9. appium-基础搭建,适配,问题,优化,提速

    搭建开发环境,导入testng/log4j/maven 1.配置jdk环境 2.安装appium,下载eclipse-adt,配置appium环境 github.com/getlantern/foru ...

  10. update linux dns,no need restart

    [root@hc--uatbeta2 ~]# cd /etc[root@hc--uatbeta2 etc]# vi resolv.conf ******* nameserver 10.123.23.*