P3297 [SDOI2013]逃考

题意

两个亲戚间的范围的分界线必定为两者连线的中垂线,因此我们用半平面交\(O(n^2\log n)\)求出每个人的范围,之后相邻的两个范围连边跑最短路即可。

注意特判\(n=0\)的情况。

code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=610;
const double eps=1e-8;
const double inf=1e12;
const double Pi=acos(-1.0);
int T,n,m,tot,cnt_edge,st;
int head[maxn],dis[maxn];
double sx,sy,limx,limy;
bool vis[maxn];
struct edge{int to,nxt;}e[maxn*maxn];
inline void add_edge(int u,int v)
{
    e[++cnt_edge].nxt=head[u];
    head[u]=cnt_edge;
    e[cnt_edge].to=v;
}
struct Point
{
    double x,y;
    inline double len(){return sqrt(x*x+y*y);}
    Point operator+(const Point a)const{return (Point){x+a.x,y+a.y};}
    Point operator-(const Point a)const{return (Point){x-a.x,y-a.y};}
    Point operator*(const double k){return (Point){x*k,y*k};}
    Point operator/(const double k){return (Point){x/k,y/k};}
    double operator*(const Point a)const{return x*a.y-y*a.x;}
    double operator&(const Point a)const{return x*a.x+y*a.y;}
}p[maxn];
inline int dcmp(double x)
{
    if(fabs(x)<=eps)return 0;
    return x<0?-1:1;
}
inline Point get(Point a,Point b){return b-a;}
inline Point turn(Point a,double theta){return (Point){-a.y,a.x};}
struct Line
{
    Point p,v;int id;double theta;
    bool operator<(const Line& a)const
    {
        return !dcmp(theta-a.theta)?dcmp(get(p,v)*get(p,a.v))<0:dcmp(theta-a.theta)<0;
    }
}line[maxn],q[maxn];
inline Point getpoint(Line l1,Line l2)
{
    Point p1=l1.p,v1=l1.v,p2=l2.p,v2=l2.v;
    v1=get(p1,v1),v2=get(p2,v2);
    Point u=get(p1,p2);
    return p2+v2*(u*v1)/(v1*v2);
}
inline bool check(Line a,Line b,Line c)
{
    Point p=getpoint(a,b);
    return dcmp(get(c.p,c.v)*get(c.p,p))<=0;
}
inline void solve(int id)
{
    for(int i=1;i<=tot;i++)line[i].theta=atan2(line[i].v.y-line[i].p.y,line[i].v.x-line[i].p.x);
    sort(line+1,line+tot+1);
    int cnt=0;line[0].theta=inf;
    for(int i=1;i<=tot;i++)if(line[i].theta!=line[i-1].theta)line[++cnt]=line[i];
    tot=cnt;
    int l,r;
    q[l=r=1]=line[1];q[++r]=line[2];
    for(int i=3;i<=tot;i++)
    {
        while(l<r&&check(q[r-1],q[r],line[i]))r--;
        while(l<r&&check(q[l],q[l+1],line[i]))l++;
        q[++r]=line[i];
    }
    while(l<r&&check(q[r-1],q[r],q[l]))r--;
    while(l<r&&check(q[l],q[l+1],q[r]))l++;
    for(int i=l;i<=r;i++)add_edge(id,q[i].id);
    bool flag=1;
    for(int i=l;i<=r;i++)if(dcmp(get(q[i].p,q[i].v)*get(q[i].p,(Point){sx,sy}))<=0)flag=0;
    if(flag)st=id;
}
inline Line get_line(int x,int y)
{
    Point z=(p[x]+p[y])/2.0;
    return (Line){z,z+turn(get(p[x],p[y]),Pi/2.0),y,0};
}
inline void work(int id)
{
    tot=0;
    Point p1=(Point){0,0},p2=(Point){limx,0},p3=(Point){limx,limy},p4=(Point){0,limy};
    line[++tot]=(Line){p1,p2,n+1,0};
    line[++tot]=(Line){p2,p3,n+1,0};
    line[++tot]=(Line){p3,p4,n+1,0};
    line[++tot]=(Line){p4,p1,n+1,0};
    for(int i=1;i<=n;i++)if(i!=id)line[++tot]=get_line(id,i);
    solve(id);
}
inline void spfa()
{
    memset(dis,0x3f,sizeof(dis));
    queue<int>q;
    q.push(st);dis[st]=0;vis[st]=1;
    while(!q.empty())
    {
        int x=q.front();q.pop();vis[x]=0;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to;
            if(dis[y]>dis[x]+1)
            {
                dis[y]=dis[x]+1;
                if(!vis[y])q.push(y),vis[y]=1;
            }
        }
    }
}
int main()
{
    //freopen("test.in","r",stdin);
    //freopen("test.out","w",stdout);
    scanf("%d",&T);
    while(T--)
    {
        memset(head,0,sizeof(head));
        cnt_edge=st=0;
        scanf("%d",&n);
        scanf("%lf%lf%lf%lf",&limx,&limy,&sx,&sy);
        for(int i=1;i<=n;i++)scanf("%lf%lf",&p[i].x,&p[i].y);
        if(!n){puts("0");continue;}
        for(int i=1;i<=n;i++)work(i);
        spfa();
        printf("%d\n",dis[n+1]);
    }
    return 0;
} 

原文地址:https://www.cnblogs.com/nofind/p/12244717.html

时间: 2024-10-09 13:20:24

P3297 [SDOI2013]逃考的相关文章

Luogu3297 SDOI2013逃考(半平面交+最短路)

把每个人的监视范围看成点,相邻的两个监视范围连边,那么跑一遍最短路就可以了(事实上边权都为1可以直接bfs).显然最优的话不会有某个时刻同时被多人监视,要跨过去的话完全可以经过分界线而不是交点. 现在问题是怎么求出哪些监视范围相邻.考虑对于某个人的监视范围求出所有与它相邻的.两个监视范围的公共边是这两个人连线的中垂线,把这些线画出来可以发现求个半平面交就好了.注意线要求在矩形范围内.如果直线在半平面交中只剩下一个点应该去掉. #include<iostream> #include<cst

[半平面交][最短路]JZOJ 3297 【SDOI2013】逃考

Description 高考又来了,对于不认真读书的来讲真不是个好消息.为了小杨能在家里认真读书,他的亲戚决定驻扎在他的家里监督他学习,有爷爷奶奶.外公外婆.大舅.大嫂.阿姨……小杨实在是忍无可忍了,这种生活跟监狱有什么区别!为了他亲爱的小红,为了他的dota,他决定越狱!假设小杨的家是个n*m 的矩阵,左下角坐标为(0,0),右上角坐标为(x1,y1).小杨有n 个亲戚,驻扎在矩阵里(位置不同,且不在矩阵的边上).小杨家里的每个地方都被亲戚监控着,而且只被距离最近的亲戚监控:也就是说假设小杨所

退役前的做题记录5.0

退役前的做题记录5.0 出于某种原因新开了一篇. [CodeChef]Querying on a Grid 对序列建立分治结构,每次处理\((l,mid,r)\)时,以\(mid\)为源点建立最短路树,这样跨越\(mid\)的点对之间的最短路一定会经过\(mid\),因此两点之间的最短路径就可以描述成最短路树上的两段到根路径.对每棵最短路树处理\(dfs\)序,用树状数组维护权值修改即可. [Wannafly挑战赛4F]线路规划 类似SCOI2016萌萌哒一题,并查集\(f_{i,j}\)表示从

退役前的做题记录3

[CERC2017]Gambling Guide 设 \(f_u\) 表示 \(u\) 到 \(n\) 的期望. \(f_n=0\) \[f_u=1+\sum_{v\in suf_v}\frac{min(f_u,f_v)}{d_u}\] \[\rightarrow f_u=1+\sum_{v\in suf_u,f_v<f_u}\frac{f_v}{d_u}+\sum_{v\in suf_u,f_v\ge f_u}\frac{f_u}{d_u}\] \[\rightarrow f_u=\sum_{

克最通月值得白真员工存段况外引dsym

家卫生健康委员会卫生应急办公室组织编制了公民卫生应急素养条目,并在"4·15全民国家安全教育日"发布.条目共12条,涉及突发公共卫生事件应对,突发事件紧急医学救援.中毒及核和辐射应急处置等基本知识和要求.期望通过发布公民卫生应急素养条目,进一步提高民众卫生应急素养,推进卫生应急社会参与工作,切实维护公民生命安全和身体健康. http://weibo.com/p2018_04_18.Pp/230927981149922743777879派褐麓记杂XWO琶追斡晾 http://weibo.

马委还现收到结则者划题头对

即写五过给且都适加切正干取比生路需无万命复育米容查识提动天分子来速门能路求东意真权手很学每从设专相于长和车容色内等团来完会得机百走起去种无他产加识三说六干题来此技变很运接三事水声院正电声精活就三深了 上克油照难复九张系院包都具委化应路求按集当适据日切全化我红具院身代引多按志二民查声观际引造来同间资同四便军铁收林等历正 管的你不都一六包压律处九特把能题写层易切阶再道都列或起路是条济江象委他质养志府照员间各能济命专除习两构选身上系见对京日除问提型子任维战石给因当无 根消效学入今感省门积火学好专许义少

人生最终的逆境叫死亡,谁也逃不过

我的朋友,台北市的前副市长,曾遭受所谓"不白之冤",同时遭受党外及党内高层的斗争.后者尤其令她寒心.在此之前,她领着一笔不大不小的公俸,每日睡眠不足五小时,兢兢业业地尽责她的工作.她从高位跌下来了,辞职,而党内高层及舆论仍未放过她,继续"追杀". 她每日夜里电话中向我哭诉,愤恨不平,足不出户,关闭自己.于是我请她至我的山中书房,告诉她这里有几辈子都读不完的书与听不完的音乐,有一张安静的书桌.我告诉她坐下来,就是宁静,并劝她:割掉缠缘吧.但她仍无法安静,心仍不平. 于

8.8联考题解

今天的T1让我怀疑我是不是在做奥赛题--这考的是什么知识点啊这个,会不会用绝对值函数? Evensgn 的债务 时间限制: 1 Sec  内存限制: 128 MB 题目描述 Evensgn 有一群好朋友,他们经常互相借钱.假如说有三个好朋友A,B,C.A 欠 B 20 元,B 欠 C 20 元,总债务规模为 20+20=40 元.Evensgn 是个追求简约的人,他觉得这样的债务太繁杂了.他认为,上面的债务可以完全等价为 A 欠C20 元,B 既不欠别人,别人也不欠他.这样总债务规模就压缩到了 

软考网络工程师复习备考策略

软考网络工程师,是软考中级科目考试里面较为简单的一门科目,并且对个人专业技术提升非常有帮助.大家可以免费学习一下,徐老师在51上的最新免费备考视频.1小时学会如何高效备战软考网络工程师视频课程有技术方面的问题都可随时在课后留言.