题意:

平面上有n条线段,一次给出这n条线段的两个端点的坐标。问怪兽能否从坐标原点逃到无穷远处。(两直线最多有一个交点,且没有三线共交点的情况)

分析:

首先说明一下线段的规范相交:就是交点唯一而且在两条线段的内部。

如果输入中有一条线段uv没有和其他任何一条线段规范相交,那么怪兽一定是可以从u走到v的。

所以我们可以建一个图模型,如果u可以走到v则添加一条边,最后BFS一下看能否从起点走到终点。

再考虑下特殊情况:

题中虽然说三线不会共交点,但貌似不包括三线共端点的情况。

比如这种情况:

线段AB和BC均不和其他线段规范相交,所以会认为A能走到B,B能走到C。但事实上,这个三角形是封闭的,内部和外部不是连通的。

解决办法就是将线段适当加宽一下(代码中使线段想两侧延伸了1e-6),使其变为规范相交。

还有一种情况就是:

当两个共端点的线段共线的时候,也会出现问题。比如本来应该是封闭的,但因为是根据线段的规范相交来判断是否前进的,所以可能使其变成一条通路。

解决办法就是加宽后端点位于其他线段上的点不参与构图。

 //#define LOCAL
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <vector>
using namespace std; const double eps = 1e-;
int dcmp(double x)
{
if(fabs(x) < eps) return ;
else return x < ? - : ;
} struct Point
{
double x, y;
Point(double x=, double y=):x(x), y(y) {}
};
typedef Point Vector; Point operator + (const Point& a, const Point& b) { return Point(a.x+b.x, a.y+b.y); }
Point operator - (const Point& a, const Point& b) { return Point(a.x-b.x, a.y-b.y); }
Vector operator * (const Vector& a, double p) { return Vector(a.x*p, a.y*p); }
Vector operator / (const Vector& a, double p) { return Vector(a.x/p, a.y/p); }
bool operator < (const Point& a, const Point& b)
{
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
bool operator == (const Point& a, const Point& b)
{
return a.x == b.x && a.y == b.y;
}
double Dot(const Vector& a, const Vector& b) { return a.x*b.x + a.y*b.y; }
double Cross(const Vector& a, const Vector& b) { return a.x*b.y - a.y*b.x; }
double Length(const Vector& a) { return sqrt(Dot(a, a)); }
bool SegmentProperIntersection(const Point& a1, const Point& a2, const Point& b1, const Point& b2)
{
double c1 = Cross(a2-a1, b1-a1), c2 = Cross(a2-a1, b2-a1);
double c3 = Cross(b2-b1, a1-b1), c4 = Cross(b2-b1, a2-b1);
return dcmp(c1)*dcmp(c2) < && dcmp(c3)*dcmp(c4) < ;
} bool OnSegment(const Point& p, const Point& a, const Point& b)
{
return dcmp(Cross(a-p, b-p)) == && dcmp(Dot(a-p, b-p)) < ;
} const int maxn = + ;
int n, V;
int G[maxn][maxn], vis[maxn];
Point p1[maxn], p2[maxn]; bool OnAnySegment(const Point& p)
{
for(int i = ; i < n; ++i)
if(OnSegment(p, p1[i], p2[i])) return true;
return false;
} bool IntersectionWithAnySegment(const Point& a, const Point& b)
{
for(int i = ; i < n; ++i)
if(SegmentProperIntersection(a, b, p1[i], p2[i])) return true;
return false;
} bool dfs(int u)
{
if(u == ) return true;
vis[u] = ;
for(int v = ; v < V; ++v)
if(G[u][v] && !vis[v] && dfs(v)) return true;
return false;
} bool find_path()
{
vector<Point> vertices;
vertices.push_back(Point(0.0, 0.0));
vertices.push_back(Point(1e5, 1e5));
for(int i = ; i < n; ++i)
{
if(!OnAnySegment(p1[i])) vertices.push_back(p1[i]);
if(!OnAnySegment(p2[i])) vertices.push_back(p2[i]);
}
V = vertices.size();
memset(G, , sizeof(G));
memset(vis, , sizeof(vis));
for(int i = ; i < V; ++i)
for(int j = i+; j < V; ++j)
if(!IntersectionWithAnySegment(vertices[i], vertices[j]))
G[i][j] = G[j][i] = ;
return dfs();
} int main(void)
{
#ifdef LOCAL
freopen("2797in.txt", "r", stdin);
#endif while(scanf("%d", &n) == && n)
{
double x1, y1, x2, y2;
for(int i = ; i < n; ++i)
{
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
Point a = Point(x1, y1);
Point b = Point(x2, y2);
double l = Length(a-b);
Vector v0 = (a-b) / l * 1e-;
p1[i] = a + v0;
p2[i] = b - v0;
}
if(find_path()) puts("no");
else puts("yes");
} return ;
}

代码君

LA 2797 (平面直线图PLSG) Monster Trap的更多相关文章

  1. LA 2797 平面区域dfs

    题目大意:一个平面区域有n条线段,问能否从(0,0)处到达无穷远处(不穿过任何线段) 分析:若两条线段有一个端点重合,这种情况是不能从端点重合处穿过的 的.因此对每个端点延长一点,就可以避免这个问题. ...

  2. 8-Highcharts曲线图之对数直线图

    <!DOCTYPE> <html lang='en'> <head> <title>8-Highcharts曲线图之对数直线图</title> ...

  3. uvalive 2797 Monster Trap

    题意:给定一些线段障碍,判断怪物能不能逃离到无穷远处. 思路:从(0,0)点能否到无穷远处.用BFS搜索.那满足什么样的点符合要求,能加入到图中呢? 遍历每个点,显然一开始已经在某些线段上的点要删去. ...

  4. LA 3263 平面划分

    Little Joey invented a scrabble machine that he called Euler, after the great mathematician. In his ...

  5. canvas实现平面迁徙图

    前言 最近在做自己维护的一个可视化工具的时候,在添加基于echart的雷达图的时候,按照echart官网案例写完发现在自己项目中无法正常运行,排查了一番发现是我项目中echart的版本太低.找到问题原 ...

  6. 第三方Charts绘制图表四种形式:饼状图,雷达图,柱状图,直线图

    对于第三方框架Charts(Swift版本,在OC项目中需要添加桥接头文件),首先要解决在项目中集成的问题,集成步骤: 一.下载Charts框架 下载地址:https://github.com/dan ...

  7. LA2797 Monster Trap

    题意 PDF 分析 可以考虑建图,跑迷宫. 然后以线段端点,原点,和无穷大点建图,有边的条件是两点连线和墙没有交点. 但是对两个线段的交点处理就会有问题,所以把线段延长.另外还需要判断延长后在墙上,舍 ...

  8. BZOJ 1007: [HNOI2008]水平可见直线 平面直线

    1007: [HNOI2008]水平可见直线 Description 在xoy直角坐标平面上有n条直线L1,L2,...Ln,若在y值为正无穷大处往下看,能见到Li的某个子线段,则称Li为可见的,否则 ...

  9. LA 2797

    题目链接 题意:训练指南283页: #include <iostream> #include <cstdio> #include <cstring> #includ ...

随机推荐

  1. 如何在cocos2dx lua的回调函数里面用self

    回调里的self是另一个不同的东西了,通常是触发回调的对象,或_G或nil ,视情况而定 我的 print(self) 输出 userdata function MyClass:sayFromCall ...

  2. NeatUpload 同时选择并上传多个文件

    neatUpload是asp.net 中可以同时上传多个文件的控件,主页:http://neatupload.codeplex.com/. 效果如下图(显示有点不正常...): 使用步骤: 1. 在a ...

  3. java 获取获取字符串编码格式

    public static String getEncoding(String str) { String encode = "GB2312"; try { if (str.equ ...

  4. 后缀树(Suffix Tree)

          问题描述:               后缀树(Suffix Tree)   参考资料: http://www.cppblog.com/yuyang7/archive/2009/03/29 ...

  5. Matlab实现求a到b被c整除的个数

    我先想到的是for循环........ 然后sum(find(mod(a:b,c)==0)),从10到100得到874,为什么不对呢? 比如a = [1 2 3 4  2 3 4 2],find(a= ...

  6. HDU 2489 Minimal Ratio Tree(dfs枚举+最小生成树)

    想到枚举m个点,然后求最小生成树,ratio即为最小生成树的边权/总的点权.但是怎么枚举这m个点,实在不会.网上查了一下大牛们的解法,用dfs枚举,没想到dfs还有这么个作用. 参考链接:http:/ ...

  7. 转: 在.NET中操作数字证书

    作者:玄魂出处:博客2010-06-23 12:05 http://winsystem.ctocio.com.cn/19/9492019.shtml .NET为我们提供了操作数字证书的两个主要的类,分 ...

  8. 如何防止通过IP地址访问Tomcat管理页面

    方法:建议修改webapps下面的原始文件夹的名称,比如加一个后缀: 当需要用管理页面的时候,可以将含有manager的文件夹的后缀去掉即可 manager和host-manager共2个文件夹

  9. struts2学习笔记(3)——struts2的局部类型转换

    今天又学到了一个新的东西,就是struts2的类型转换. 为什么要类型转换? 今天我就要传一个点的坐标给你,保存时用一个自定义的Point类来保存. 因为在表单里面传过去的是字符串,如“12,23”, ...

  10. 前端H5开发工具 Adobe Edge

    http://www.cnblogs.com/adobeedge/ http://my.oschina.net/duolus/blog/212801?fromerr=WAcqscJl