P3297 [SDOI2013]逃考
完全看不出这思路是怎么来的……
首先对于两个亲戚,他们监视范围的边界是他们连线的中垂线。那么对于一个亲戚来说它能监视的范围就是所有的中垂线形成的半平面交
然后如果某两个亲戚的监视范围有公共边,那么就在这两个亲戚之间连一条边,如果某个亲戚的监视范围和矩阵边界有公共边,那么就把这个亲戚和终点连边。然后以一开始监视的亲戚为起点,跑一遍最短路即可
//minamoto
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
using namespace std;
int read(){
int res,f=1;char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=10005;
int S,T,n,times,sx,sy,bx,by,no[N],m;
struct Graph{
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void clr(){tot=0;memset(head,0,sizeof(head));}
inline void add(int u,int v){e[++tot]={v,head[u]},head[u]=tot;}
int dis[N],q[N];bool vis[N];
int spfa(){
fp(i,1,n+1)dis[i]=inf,vis[i]=0;
int h=0,t=1;dis[S]=0,q[h]=S;
while(h!=t){
int u=q[h++];vis[u]=0;if(h==N)h-=N;
go(u)if(dis[v]>dis[u]+1){
dis[v]=dis[u]+1;
if(!vis[v]){
q[t++]=v,vis[v]=1;
if(t==N)t-=N;
}
}
}return dis[T];
}
}G;
struct node{double x,y;}p[N];
struct line{
node a,b;int id;double sl;
inline line(){}
inline line(node a,node b,int id):a(a),b(b),id(id){sl=atan2(b.y-a.y,b.x-a.x);}
}q[N],a[N],l[N];
inline node operator +(node a,node b){return {a.x+b.x,a.y+b.y};}
inline node operator -(node a,node b){return {a.x-b.x,a.y-b.y};}
inline double operator *(node a,node b){return a.x*b.y-a.y*b.x;}
inline bool operator <(line a,line b){return a.sl==b.sl?(a.b-a.a)*(b.a-a.a)<=0:a.sl<b.sl;}
node inter(line a,line b){
double k1,k2,t;
k1=(b.b-a.a)*(a.b-a.a);
k2=(a.b-a.a)*(b.a-a.a);
t=k2/(k1+k2);
return {b.a.x+t*(b.b.x-b.a.x),b.a.y+t*(b.b.y-b.a.y)};
}
inline bool jd(line a,line b,line c){node p=inter(a,b);return (p-c.a)*(c.b-c.a)>0;}
void hpi(int st){
int tot=0;sort(l+1,l+1+m);
fp(i,1,m)if(l[i].sl!=a[tot].sl)a[++tot]=l[i];
int h=1,t=0;q[++t]=a[1],q[++t]=a[2];
fp(i,3,tot){
while(h<t&&jd(q[t-1],q[t],a[i]))--t;
while(h<t&&jd(q[h+1],q[h],a[i]))++h;
q[++t]=a[i];
}
while(h<t&&jd(q[t-1],q[t],q[h]))--t;
while(h<t&&jd(q[h+1],q[h],q[t]))++h;
fp(i,h,t)G.add(st,q[i].id);
}
void clr(){G.clr(),memset(no,0,sizeof(no));}
double dis(node a,node b){return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);}
node rotate(node a){return {-a.y,a.x};}
node getmid(node a,node b){return {(a.x+b.x)/2,(a.y+b.y)/2};}
void init(int st){
l[1]=line({0,0},{sx,0},n+1),l[2]=line({sx,0},{sx,sy},n+1);
l[3]=line({sx,sy},{0,sy},n+1),l[4]=line({0,sy},{0,0},n+1);
m=4;
fp(i,1,n)if(i!=st&&!no[i]){
node mid=getmid(p[i],p[st]);
node v=rotate(p[i]-p[st]);
l[++m]=line(mid,mid+v,i);
}
}
void solve(){
clr(),n=read(),sx=read(),sy=read(),bx=read(),by=read();
node res={bx,by};
if(!n)return (void)(puts("0"));
T=n+1;int pos=0;double len=1e15;
fp(i,1,n){
p[i].x=read(),p[i].y=read();
if(p[i].x>sx||p[i].y>sy)no[i]=1;
double now=dis(p[i],res);
if(now<len)len=now,pos=i;
}S=pos;
fp(i,1,n)if(!no[i])init(i),hpi(i);
printf("%d\n",G.spfa());
}
int main(){
// freopen("testdata.in","r",stdin);
times=read();
while(times--)solve();
return 0;
}
P3297 [SDOI2013]逃考的更多相关文章
- 洛谷 P3297 [SDOI2013]逃考 解题报告
P3297 [SDOI2013]逃考 题意 给一个平面矩形,里面有一些有标号点,有一个是人物点,人物点会被最近的其他点控制,人物点要走出矩形,求人物点最少被几个点控制过. 保证一开始只被一个点控制,没 ...
- luogu P3297 [SDOI2013]逃考
传送门 gugugu 首先每个人管理的区域是一个多边形,并且整个矩形是被这样的多边形填满的.现在的问题是求一条经过多边形最少的路径到达边界,这个可以最短路. 现在的问题是建图,显然我们应该给相邻的多边 ...
- BZOJ3199 SDOI2013 逃考 半平面交、最短路
传送门 如果我们对于每一个点能找到与其相邻的点(即不经过其他点监视范围能够直接到达其监视范围的点)和是否直接到达边界,就可以直接BFS求最短路求出答案. 所以当前最重要的问题是如何找到对于每一个点相邻 ...
- Luogu3297 SDOI2013逃考(半平面交+最短路)
把每个人的监视范围看成点,相邻的两个监视范围连边,那么跑一遍最短路就可以了(事实上边权都为1可以直接bfs).显然存在最优路线没有某个时刻同时被多于两人监视,要到达另一个区域的话完全可以经过分界线而不 ...
- [JZOJ3297] 【SDOI2013】逃考
题目 我发现我现在连题面都懒得复制粘贴了-- 题目大意 在一个矩形中有一堆点,这堆点按照以下规则将矩形瓜分成一堆块: 对于每个坐标,它属于离它最近的点的块. 一个人从某个坐标出发到矩形外面,求经过的最 ...
- 【JZOJ3297】【SDOI2013】逃考(escape)
Mission 高考又来了,对于不认真读书的来讲真不是个好消息.为了小杨能在家里认真读书,他的亲戚决定驻扎在他的家里监督他学习,有爷爷奶奶.外公外婆.大舅.大嫂.阿姨-- 小杨实在是忍无可忍了,这种生 ...
- 2014秋C++第5周项目1參考-见识刚開始学习的人常见错误
课程主页在http://blog.csdn.net/sxhelijian/article/details/39152703,实践要求见http://blog.csdn.net/sxhelijian/a ...
- C++常考面试题汇总
c++面试题 一 用简洁的语言描述 c++ 在 c 语言的基础上开发的一种面向对象编程的语言: 应用广泛: 支持多种编程范式,面向对象编程,泛型编程,和过程化编程:广泛应用于系统开发,引擎开发:支持类 ...
- AWS的SysOps认证考试样题解析
刚考过了AWS的developer认证,顺手做了一下SysOps的样题.以下是题目和答案. When working with Amazon RDS, by default AWS is respon ...
随机推荐
- android 上AES解密是报错javax.crypto.BadPaddingException: pad block corrupted
网上看到两种方法: 1.SecretKeySpec skeySpec = new SecretKeySpec(getRawKey(key), "AES"); private sta ...
- PatentTips – EMC Virtual File System
BACKGROUND OF THE INVENTION 1. Field of the Invention The present invention generally relates to net ...
- EditText实时监测内容
editText.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequ ...
- 交互设计:隐藏或显示大段文本的UI组件有哪些?
应用场景: 在手机上要给列表中的每一项添加一个大段的介绍,应该用什么UI组件 A: 这里可以用,模态对话框,弹出提示,工具提示这类组件.模态对话框的好处,就是用关闭的按钮,用户操作方便:而弹出提示和工 ...
- hadoop(1)入门
hadoop入门(一) 一.概述 1.什么是hadoop hadoop不仅是一个用于存储分布式文件系统,还是设计用来在有通用计算设备组成的大型集群上执行的分布式应用的基础框架. hadoop框架最 ...
- 洛谷 P1555 尴尬的数字
P1555 尴尬的数字 题目背景 Bessie刚刚学会了不同进制数之间的转换,但是她总是犯错误,因为她的两个前蹄不能轻松的握住钢笔. 题目描述 每当Bessie将一个数转换成新的进制时,她总会写错一位 ...
- CCNA参考链接
http://www.cisco.com/c/en/us/support/docs/lan-switching/vtp/10558-21.html http://www.cisco.com/c/en/ ...
- VMWare9下基于Ubuntu12.10搭建Hadoop-1.2.1集群—整合Zookeeper和Hbase
VMWare9下基于Ubuntu12.10搭建Hadoop-1.2.1集群-整合Zookeeper和Hbase 这篇是接着上一篇hadoop集群搭建进行的.在hadoop-1.2.1基础之上安装zoo ...
- for in、for和EnumerateObjectsUsingBlock遍历的区别
1.对于集合中对象数很多的情况下,for in 的遍历速度非常之快,但小规模的遍历并不明显(还没普通for循环快) 2. 如果在for in 循环里,对这个数组进行了修改的话,无论是增,删,修改数组元 ...
- Spring和SpringMVC的关系
1.Spring和SpringMVC是父子容器关系. 2.Spring整体框架的核心思想是容器,用来管理bean的生命周期,而一个项目中会包含很多容器,并且它们分上下层关系,目前最常用的一个场景是在一 ...