传送门

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. java 数组声明定义 数组内存分配 数组初始化 数组引用 数组的遍历

    一,数组的定义 Java 中定义数组的语法有两种: 1. type arrayName[]; 2. type[] arrayName;type 为Java中的任意数据类型,包括基本类型和组合类型,ar ...

  2. QML学习笔记(七)— 实现可拖拽、编辑、选中的ListView

    鼠标单击可选中当前项,头部呈绿色显示:按压当前项可进行拖拽更换列表项位置:点击数据可以进行编辑: GitHub:八至 作者:狐狸家的鱼 这里是自己定义的model,有些字体和颜色都是使用的全局属性, ...

  3. Git中撤销提交

    Git的几种状态 未修改 原始内容 已修改 ↓ 工 作 区 已暂存 ↓ git add 暂 存 区 已提交 ↓ git commit 本地仓库 已推送 ↓ git push 远程仓库 注意:下面所有命 ...

  4. Jquery Mobile基本元素

    移动端框架 安装: CDN: <link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jq ...

  5. (string stoi 栈)leetcode682. Baseball Game

    You're now a baseball game point recorder. Given a list of strings, each string can be one of the 4 ...

  6. 微信小程序:图片预览

    wxml页面: <image src='{{UPLOAD_IMAGES_URL}}{{vv.img_s}}' data-src="{{vv.img}}" bindtap=&q ...

  7. mysql删除大表更快的drop table办法

    mysql删除大表更快的drop table办法 参考资料:https://blog.csdn.net/anzhen0429/article/details/76284320 利用硬链接和trunca ...

  8. passat QA / error code 20190210

    s 帕萨特B5 技术资料下载 https://pan.baidu.com/s/1KXYly7eGDUSI5QiLcz8fiQ 提取码: 1i7u 星期日,10,二月,2019,17:16:16:317 ...

  9. HTML5 accesskey的用法

    <button onclick="start()" accesskey="s">开始</button> <button oncli ...

  10. ACM-ICPC 2018 南京赛区网络预赛 J Sum (思维+打表)

    https://nanti.jisuanke.com/t/30999 题意 f(i)表示i能拆分成两个数的乘积,且要求这两个数中各自都没有出现超过1次的质因子的方案数.每次给出n,求∑(n,i=1)f ...