传送门

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. bzoj1398 Necklace

    关于最小表示法的模板题. 最小表示法:把一个字符串表示为它的的所有循环同构字符串中的字典序最小者. 直接参见代码中的函数getmin()获取精髓 #include <cstdio> #in ...

  2. A1131. Subway Map (30)

    In the big cities, the subway systems always look so complex to the visitors. To give you some sense ...

  3. 【CF1042D】Petya and Array 离散化+树状数组

    题目大意:给定一个长度为 N 的序列,给定常数 t,求有多少个区间 [l,r] 满足 \(\sum\limits_{i=l}^{r}a_i<t\). 题解:先跑一边前缀和,问题等价于求有多少个数 ...

  4. Python线程状态和全局解释器锁

    在刚接触Python的时候时常听到GIL这个词,并且发现这个词经常和Python无法高效的实现多线程划上等号.本着不光要知其然,还要知其所以然的研究态度,博主搜集了各方面的资料,花了一周内几个小时的闲 ...

  5. 基于django的自定义简单session功能

    基于django的自定义简单session功能 简单思路: 1.建立自定义session数据库 2.登入时将用户名和密码存入session库 3.将自定义的随机session_id写入cookie中 ...

  6. 第三十节,目标检测算法之Fast R-CNN算法详解

    Girshick, Ross. “Fast r-cnn.” Proceedings of the IEEE International Conference on Computer Vision. 2 ...

  7. 对于Arrays的deep相关的方法。

    关于: deepEquals Arrays.equals(Object[] o1, Object[] o2):当是判断数组是引用类型数组的时候,从以下条件判断: 1.o1与o2指向同一个数组实例时,返 ...

  8. C++的静态成员变量使用方法

    main.cpp:(.text._ZN6Object4useSEv[_ZN6Object4useSEv]+0x1a):对‘Object::i’未定义的引用 常用Java不懂C++的静态方法使用方式.尝 ...

  9. 象棋start

    这篇文章其实谈的不是象棋开局,更谈不上开局技巧,举个例子:第一步走炮二平五,也即是中炮局,但中炮局可以根据对手的应对着法演变成很多,比如:五七炮对屏风马,五六炮对屏风马,顺炮局,以及雷公炮等等,这些才 ...

  10. react一看就会的简单路由设置

    不管是vue还是react  这种单页面的框架一定都少不了路由 下面给大家讲讲在实际项目中react的路由设置 第一步: 在src目录下新建一个目录route  在该目录下新建一个index.js用于 ...