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 ...
随机推荐
- python之GUI图形用户界面 2014-4-7
#图形用户界面1.下载和安装wxPython2.创建并显示一个框架import wx #导入wxPythonapp=wx.App()win=wx.Frame(None)win.Show() #调用窗口 ...
- Leetcode 179.最大数
最大数 给定一组非负整数,重新排列它们的顺序使之组成一个最大的整数. 示例 1: 输入: [10,2] 输出: 210 示例 2: 输入: [3,30,34,5,9] 输出: 9534330 impo ...
- hdu 3622 二分+2-sat
/* 二分+2-sat 题意:在一个二维平面上给你n个炸弹,和2*n个位置,每一行的两个位置只能有一个放炸弹 现在炸弹爆炸有一个半径,当炸弹爆炸时两个炸弹的半径化成的圆不能相交,求最大半径 二分半径, ...
- QQ5.0侧滑
package com.example; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; impo ...
- [bzoj1934/2768][Shoi2007]Vote 善意的投票_最小割
Vote 善意的投票 bzoj-1934 Shoi-2007 题目大意:题目链接. 注释:略. 想法: 这是最小割的一个比较基本的模型. 我们将所有当前同意的小朋友连向源点,边权为1.不容易的连向汇点 ...
- Spring Boot-Logback 配置(区分环境、分包、分级别打印)
<?xml version="1.0" encoding="UTF-8"?> <configuration> <!--生产环境 - ...
- Ubuntu 16.04安装磁盘占用分析器:ncdu
使用此工具能分析出哪个文件或者文件夹有多大,从而实现自己手动删除. 安装: sudo apt-get install ncdu 使用: #默认搜索当前用户目录 ncdu #搜索整个硬盘 ncdu /
- php-7.1编译记录
编译php-7.1.28步骤 检查环境 ./configure \ --prefix=/u01/server/php-7.1.28 \ --enable-fpm \ --with-fpm-user=d ...
- mvn打包源码的方法:maven-source-plugin
maven-javadoc-plugin可以打包 dubbo-demo-provider-2.6.1-javadoc.jar maven-jar-plugin 打包插件 dubbo-demo-prov ...
- laravel notification
mail篇 public function via($notifiable) { return ['mail']; } 1.新建notification类 php artisan make:notif ...