传送门

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. QML学习笔记(七)— 实现可拖拽、编辑、选中的ListView

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

  2. HDU/HDOJ 2087 剪花布条

    KMP裸题 (极限5分钟A题) /** freopen("in.in", "r", stdin); freopen("my.out", &q ...

  3. git的使用命令

    git archive --format zip --output "./test.zip" master -0 将项目的代码通过上述命令打包压缩为test文件夹 ssh-keyg ...

  4. Django 项目内利用ORM直接运行脚本读库

    #导包 import os import sys #将脚本所在工程添加到环境变量 #绝对路径 # sys.path.append('c:/Users/nxy/www/mymac') #相对路径 sys ...

  5. bcftools或vcftools提取指定区段的vcf文件(extract specified position )

    下载安装bcftools 见如下命令: bcftools filter 1000Genomes.vcf.gz --regions 9:4700000-4800000 > 4700000-4800 ...

  6. 激活miniconda2环境,出现activate命令不存在的解决方案(activate: No such file or directory)

    miniconda2版本比较低时会出现这种报错,通过更新miniconda2就可以解决这个问题,用到的命令行: /path/to/miniconda2/conda update conda 参考链接: ...

  7. hdu 2159FATE(完全背包)

    传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题解: 思路一:完全背包转“01”背包 考虑到第ki个怪最多杀min(m/b[ki],s ...

  8. nohup报错

    1 这是脚本编码的问题 解决办法: (1)用vi打开对应的脚本 (2)在命令行下(:set ff?),看一下当前文档的编码格式 ,有两种情况 fileformat=unix和fileformat=do ...

  9. 多元线性回归(Multivariate Linear Regression)简单应用

    警告:本文为小白入门学习笔记 数据集: http://openclassroom.stanford.edu/MainFolder/DocumentPage.php?course=DeepLearnin ...

  10. (栈)leetcode 946. Validate Stack Sequences

    Given two sequences pushed and popped with distinct values, return true if and only if this could ha ...