LA2797 Monster Trap

题意

PDF

分析

可以考虑建图,跑迷宫。

然后以线段端点,原点,和无穷大点建图,有边的条件是两点连线和墙没有交点。

但是对两个线段的交点处理就会有问题,所以把线段延长。另外还需要判断延长后在墙上,舍去这些端点。

时间复杂度\(O(T n^3)\)

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<algorithm>
#include<bitset>
#include<cassert>
#include<ctime>
#include<cstring>
#define rg register
#define il inline
#define co const
template<class T>il T read()
{
    rg T data=0;
    rg int w=1;
    rg char ch=getchar();
    while(!isdigit(ch))
    {
        if(ch=='-')
            w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
    {
        data=data*10+ch-'0';
        ch=getchar();
    }
    return data*w;
}
template<class T>T read(T&x)
{
    return x=read<T>();
}
using namespace std;
typedef long long ll;

co double eps=1e-12;
double dcmp(double x)
{
    return fabs(x)<eps?0:(x<0?-1:1);
}

struct Point
{
    double x,y;
    
    Point(double x=0,double y=0)
    :x(x),y(y){}
    
    bool operator<(co Point&p)co
    {
        return x<p.x||(x==p.x&&y<p.y);
    }
    
    bool operator==(co Point&p)co
    {
        return x==p.x&&y==p.y;
    }
};
typedef Point Vector;

Vector operator+(co Vector&A,co Vector&B)
{
    return Vector(A.x+B.x,A.y+B.y);
}

Vector operator-(co Point&A,co Point&B)
{
    return Vector(A.x-B.x,A.y-B.y);
}

Vector operator*(co Point&A,double v)
{
    return Vector(A.x*v,A.y*v);
}

Vector operator/(co Point&A,double v)
{
    return Vector(A.x/v,A.y/v);
}

double Cross(co Vector&A,co Vector&B)
{
    return A.x*B.y-A.y*B.x;
}

double Dot(co Vector&A,co Vector&B)
{
    return A.x*B.x+A.y*B.y;
}

double Length(co Vector&A)
{
    return sqrt(Dot(A,A));
}

bool SegmentProperIntersection(co Point&a1,co Point&a2,co Point&b1,co Point&b2)
{
    double c1=Cross(a2-a1,b1-a1),c2=Cross(a2-a1,b2-a1),
           c3=Cross(b2-b1,a1-b1),c4=Cross(b2-b1,a2-b1);
    return dcmp(c1)*dcmp(c2)<0&&dcmp(c3)*dcmp(c4)<0;
}

bool OnSegment(co Point&p,co Point&a1,co Point&a2)
{
    return dcmp(Cross(a1-p,a2-p))==0&&dcmp(Dot(a1-p,a2-p))<0;
}

co int MAXV=202;
int V;
int G[MAXV][MAXV],vis[MAXV];

bool dfs(int u)
{
    if(u==1)
        return 1;
    vis[u]=1;
    for(int v=0;v<V;++v)
        if(G[u][v]&&!vis[v]&&dfs(v))
            return 1;
    return 0;
}

co int MAXN=100;
int n;
Point p1[MAXN],p2[MAXN];

bool OnAnySegment(Point p)
{
    for(int i=0;i<n;++i)
        if(OnSegment(p,p1[i],p2[i]))
            return 1;
    return 0;
}

bool IntersectWithAnySegment(Point a,Point b)
{
    for(int i=0;i<n;++i)
        if(SegmentProperIntersection(a,b,p1[i],p2[i]))
            return 1;
    return 0;
}

bool find_path()
{
    vector<Point>vertices;
    vertices.push_back(Point(0,0));
    vertices.push_back(Point(1e5,1e5));
    for(int i=0;i<n;++i)
    {
        if(!OnAnySegment(p1[i]))
            vertices.push_back(p1[i]);
        if(!OnAnySegment(p2[i]))
            vertices.push_back(p2[i]);
    }
    V=vertices.size();
    for(int i=0;i<V;++i)
        fill(G[i],G[i]+V,0);
    fill(vis,vis+V,0);
    for(int i=0;i<V;++i)
        for(int j=i+1;j<V;++j)
            if(!IntersectWithAnySegment(vertices[i],vertices[j]))
                G[i][j]=G[j][i]=1;
    return dfs(0);
}

int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    while(read(n))
    {
        for(int i=0;i<n;++i)
        {
            int x1,y1,x2,y2;
            read(x1),read(y1),read(x2),read(y2);
            Point a=Point(x1,y1);
            Point b=Point(x2,y2);
            Vector v=b-a;
            v=v/Length(v);
            p1[i]=a-v*1e-6;
            p2[i]=b+v*1e-6;
        }
        puts(find_path()?"no":"yes");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/autoint/p/10173307.html
今日推荐