[Sdoi2013]escape

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3199

题解:这题的关键在于怎么求出每个家长的监视范围呢?。其实很简单。对于第i个家长,向每个家长j连线作中垂线,每条线对应一个朝向i的半平面,这些半平面的交就是第i个家长的监视范围。然后半平面交出来的多边形每条变对应的家长j,与i连边,最后bfs一下求出起始多边形到界外的最短路就好了。时间复杂度O(n^2logn)。

题解说可以用V图做,可是我不会= =。最后吐槽一下这题O(n^2)的半平面交也是可以通过的。而且跑得没比nlogn的慢多少。囧。

代码:

/**************************************************************
    Problem: 3199
    User: hta
    Language: C++
    Result: Accepted
    Time:844 ms
    Memory:8844 kb
****************************************************************/
 
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <list>
#include <queue>
#include <vector>
#include <ctime>
#include <set>
#include <bitset>
#include <deque>
#include <fstream>
#include <stack>
#include <map>
#include <utility>
#include <cassert>
#include <string>
#include <iterator>
#include <cctype>
using namespace std;
const int maxn=800,maxm=maxn*maxn;
const double eps=1e-9;
struct Tpoint
{
    double x,y;
    Tpoint(){}
    Tpoint(double _x,double _y){x=_x,y=_y;}
    Tpoint operator -(const Tpoint &b)const{return Tpoint(x-b.x,y-b.y);}
    Tpoint operator +(const Tpoint &b)const{return Tpoint(x+b.x,y+b.y);}
    Tpoint operator *(double b)const{return Tpoint(x*b,y*b);}
    double operator *(const Tpoint &b)const{return x*b.y-y*b.x;}
}S,p[maxn];
struct Tline
{
    Tpoint p1,p2;int id;
    double ang;
    Tline(){}
    Tline(Tpoint _p1,Tpoint _p2,int i){p1=_p1,p2=_p2;ang=atan2(p2.y-p1.y,p2.x-p1.x);id=i;}
}L[maxn];
double xx,yy;
bool flag,vis[maxn];
int T,n,tot=0,Q[maxn],pre[maxm],t[maxm],Link[maxn],s[maxm],d[maxn],cnt=0;
inline int get()
{
    int f=0,v=0;char ch;
    while(!isdigit(ch=getchar()))if(ch=='-')break;
    if(ch=='-')f=1;else v=ch-48;
    while(isdigit(ch=getchar()))v=v*10+ch-48;
    if(f==1)return -v;else return v;
}
inline int sig(double x){return fabs(x)<=eps?0:(x>eps?1:-1);}
inline double dist(const Tpoint &a){return sqrt(a.x*a.x+a.y*a.y);}
Tpoint lineintersect(const Tline &l1,const Tline &l2)
{
    double ta=(l1.p2-l2.p1)*(l1.p1-l2.p1);
    double tb=(l2.p2-l1.p2)*(l1.p1-l1.p2);
    Tpoint tp;
    if(sig(ta+tb)==0){flag=0;return tp;};
    tp=(l2.p2-l2.p1)*(ta/(ta+tb))+l2.p1;
    return tp;
}
 
bool cmp(const Tline &a,const Tline &b)
{
    if(sig(a.ang-b.ang)==0)return sig((a.p1-b.p1)*(b.p2-b.p1))<0;
    return sig(a.ang-b.ang)<0;
}
 
bool onleft(const Tline &l1,const Tline &l2,const Tline &l3)
{
    Tpoint tp=lineintersect(l1,l2);
    return sig((tp-l3.p1)*(l3.p2-l3.p1))<=0;//
}
 
void hpi(int x)
{
    flag=1;
    sort(L+1,L+1+tot,cmp);
    int tp=1,front=1,rear=0;
    for(int i=2;i<=tot;i++)
        if(sig(L[i].ang-L[i-1].ang)!=0)L[++tp]=L[i];
    tot=tp;
    for(int i=1;i<=tot;i++)
    {
        while(front<rear&&!onleft(L[Q[rear-1]],L[Q[rear]],L[i]))rear--;
        while(front<rear&&!onleft(L[Q[front]],L[Q[front+1]],L[i]))front++;
        if(!flag)return;
        Q[++rear]=i;
    }
    while(front<rear&&!onleft(L[Q[rear-1]],L[Q[rear]],L[Q[front]]))rear--;
    while(front<rear&&!onleft(L[Q[front]],L[Q[front+1]],L[Q[rear]]))front++;
    if(!flag)return;
    if(rear-front<2)return;
    for(int i=front;i<=rear;i++)
    {
        int y=L[Q[i]].id;
        pre[++cnt]=Link[x]; Link[x]=cnt; t[cnt]=y;
    }
}
 
void work(int x)
{
    tot=0;
    L[++tot]=Tline(Tpoint(0,0),Tpoint(xx,0),n+1);
    L[++tot]=Tline(Tpoint(xx,0),Tpoint(xx,yy),n+1);
    L[++tot]=Tline(Tpoint(xx,yy),Tpoint(0,yy),n+1);
    L[++tot]=Tline(Tpoint(0,yy),Tpoint(0,0),n+1);
    for(int i=1;i<=n;i++)
    {
        if(i==x)continue;
        Tpoint S=(p[i]+p[x])*0.5,tp=Tpoint(p[x].y-p[i].y,-(p[x].x-p[i].x)),T=S+tp;
        L[++tot]=Tline(S,T,i);
    }
    hpi(x);
}
 
int bfs(int st)
{
    int front=0,rear=1;
    memset(d,120,sizeof(d));
    memset(vis,0,sizeof(vis));
    d[st]=0;vis[st]=1;s[front]=st;
    while(front!=rear)
    {
        int p=s[front];
        for(int i=Link[p];i;i=pre[i])
            if(!vis[t[i]])d[t[i]]=d[p]+1,vis[t[i]]=1,s[rear++]=t[i];
        front++;
if(d[n+1]<n+10)break;
    }
    return d[n+1];
}
 
int main()
{
    T=get();
    while(T--)
    {
        n=get();
        xx=get(),yy=get(),S.x=get(),S.y=get();
        for(int i=1;i<=n;i++)p[i].x=get(),p[i].y=get();
        cnt=0,memset(Link,0,sizeof(Link));
        for(int i=1;i<=n;i++)work(i);
        int st=1;double tp=dist(p[1]-S);
        for(int i=2;i<=n;i++)
            if(dist(p[i]-S)<tp)tp=dist(p[i]-S),st=i;
        printf("%d\n",bfs(st));
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值