uvalive 2797 Monster Trap

题意:给定一些线段障碍,判断怪物能不能逃离到无穷远处。

思路:从(0,0)点能否到无穷远处。用BFS搜索。那满足什么样的点符合要求,能加入到图中呢?

遍历每个点,显然一开始已经在某些线段上的点要删去。再判断,两点之间的连线是否与其他线段有交。有则删去。

这道题要注意如果两条线段重合,怎么办?延长每条线段,如果交点在线段内,不算。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<memory.h>
  7 #include<cstdlib>
  8 #include<vector>
  9 #define clc(a,b) memset(a,b,sizeof(a))
 10 #define LL long long int
 11 #define up(i,x,y) for(i=x;i<=y;i++)
 12 #define w(a) while(a)
 13 const double inf=0x3f3f3f3f;
 14 const int N = 4010;
 15 const double PI = acos(-1.0);
 16 using namespace std;
 17 const double eps = 1e-12;
 18
 19 double dcmp(double x)
 20 {
 21     if(fabs(x) < eps) return 0;
 22     else return x < 0 ? -1 : 1;
 23 }
 24
 25 struct Point
 26 {
 27     double x, y;
 28     Point(double x=0, double y=0):x(x),y(y) { }
 29 };
 30
 31 typedef Point Vector;
 32
 33 Vector operator + (const Point& A, const Point& B)
 34 {
 35     return Vector(A.x+B.x, A.y+B.y);
 36 }
 37
 38 Vector operator - (const Point& A, const Point& B)
 39 {
 40     return Vector(A.x-B.x, A.y-B.y);
 41 }
 42
 43 Vector operator * (const Point& A, double v)
 44 {
 45     return Vector(A.x*v, A.y*v);
 46 }
 47
 48 Vector operator / (const Point& A, double v)
 49 {
 50     return Vector(A.x/v, A.y/v);
 51 }
 52
 53 double Cross(const Vector& A, const Vector& B)
 54 {
 55     return A.x*B.y - A.y*B.x;
 56 }
 57
 58 double Dot(const Vector& A, const Vector& B)
 59 {
 60     return A.x*B.x + A.y*B.y;
 61 }
 62
 63 double Length(const Vector& A)
 64 {
 65     return sqrt(Dot(A,A));
 66 }
 67
 68 bool operator < (const Point& p1, const Point& p2)
 69 {
 70     return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y);
 71 }
 72
 73 bool operator == (const Point& p1, const Point& p2)
 74 {
 75     return p1.x == p2.x && p1.y == p2.y;
 76 }
 77
 78 bool SegmentProperIntersection(const Point& a1, const Point& a2, const Point& b1, const Point& b2)
 79 {
 80     double c1 = Cross(a2-a1,b1-a1), c2 = Cross(a2-a1,b2-a1),
 81            c3 = Cross(b2-b1,a1-b1), c4=Cross(b2-b1,a2-b1);
 82     return dcmp(c1)*dcmp(c2)<0 && dcmp(c3)*dcmp(c4)<0;
 83 }
 84
 85 bool OnSegment(const Point& p, const Point& a1, const Point& a2)
 86 {
 87     return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
 88 }
 89
 90 const int maxv = 200 + 5;
 91 int V;
 92 int G[maxv][maxv], vis[maxv];
 93
 94 bool dfs(int u)
 95 {
 96     if(u == 1) return true; // 1是终点
 97     vis[u] = 1;
 98     for(int v = 0; v < V; v++)
 99         if(G[u][v] && !vis[v] && dfs(v)) return true;
100     return false;
101 }
102
103 const int maxn = 100 + 5;
104 int n;
105 Point p1[maxn], p2[maxn];
106
107 // 在任何一条线段的中间(在端点不算)
108 bool OnAnySegment(Point p)
109 {
110     for(int i = 0; i < n; i++)
111         if(OnSegment(p, p1[i], p2[i])) return true;
112     return false;
113 }
114
115 // 与任何一条线段规范相交
116 bool IntersectWithAnySegment(Point a, Point b)
117 {
118     for(int i = 0; i < n; i++)
119         if(SegmentProperIntersection(a, b, p1[i], p2[i])) return true;
120     return false;
121 }
122
123 bool find_path()
124 {
125     // 构图
126     vector<Point> vertices;
127     vertices.push_back(Point(0, 0)); // 起点
128     vertices.push_back(Point(1e5, 1e5)); // 终点
129     for(int i = 0; i < n; i++)
130     {
131         if(!OnAnySegment(p1[i])) vertices.push_back(p1[i]);
132         if(!OnAnySegment(p2[i])) vertices.push_back(p2[i]);
133     }
134     V = vertices.size();
135     memset(G, 0, sizeof(G));
136     memset(vis, 0, sizeof(vis));
137     for(int i = 0; i < V; i++)
138         for(int j = i+1; j < V; j++)
139             if(!IntersectWithAnySegment(vertices[i], vertices[j]))
140                 G[i][j] = G[j][i] = 1;
141     return dfs(0);
142 }
143
144 int main()
145 {
146     while(cin >> n && n)
147     {
148         for(int i = 0; i < n; i++)
149         {
150             double x1, y1, x2, y2;
151             cin >> x1 >> y1 >> x2 >> y2;
152             Point a = Point(x1, y1);
153             Point b = Point(x2, y2);
154             Vector v = b - a;
155             v = v / Length(v);
156             p1[i] = a + v * 1e-6;
157             p2[i] = b + v * 1e-6;
158         }
159         if(find_path()) cout << "no\n";
160         else cout << "yes\n";
161     }
162     return 0;
163 }

时间: 2024-10-06 10:05:37

uvalive 2797 Monster Trap的相关文章

uva 1318 - Monster Trap(bfs+暴力)

题目链接:uva 1318 - Monster Trap 每条线段2个点,加上起点终点一个是202个点,暴力判断连点之间是否可达,可达建边.因为线段有厚度考虑,所以将线段延伸一点再处理,这样原本共用一端点的线段变成相交.特殊情况是三点共线,这是判断延伸后的点是否落在其他线段上,如果是就不考虑这个点.最后做一遍bfs. #include <cstdio> #include <cstring> #include <cmath> #include <vector>

LA 2797 (平面直线图PLSG) Monster Trap

题意: 平面上有n条线段,一次给出这n条线段的两个端点的坐标.问怪兽能否从坐标原点逃到无穷远处.(两直线最多有一个交点,且没有三线共交点的情况) 分析: 首先说明一下线段的规范相交:就是交点唯一而且在两条线段的内部. 如果输入中有一条线段uv没有和其他任何一条线段规范相交,那么怪兽一定是可以从u走到v的. 所以我们可以建一个图模型,如果u可以走到v则添加一条边,最后BFS一下看能否从起点走到终点. 再考虑下特殊情况: 题中虽然说三线不会共交点,但貌似不包括三线共端点的情况. 比如这种情况: 线段

[GodLove]Wine93 Tarining Round #10

比赛链接: http://www.bnuoj.com/v3/contest_show.php?cid=4159 题目来源: lrj训练指南---几何算法 Flag ID Title   A Board Wrapping   B Airport   C The Great Divide   D Squares   E Most Distant Point from the Sea   F Triathlon   G Jungle Outpost   H Monster Trap   I Find

UVALive 4848 Tour Belt

F - Tour Belt Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVALive 4848 Description Korea has many tourist attractions. One of them is an archipelago (Dadohae in Korean), a cluster of small islands sca

UVALive 6467 Strahler Order 拓扑排序

这题是今天下午BNU SUMMER TRAINING的C题 是队友给的解题思路,用拓扑排序然后就可以了 最后是3A 其中两次RE竟然是因为: scanf("%d",mm); ORZ 以后能用CIN还是CIN吧 QAQ 贴代码了: 1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <math.h> 5 #include <iostre

UVALive 7077 Little Zu Chongzhi&#39;s Triangles (有序序列和三角形的关系)

这个题……我上来就给读错了,我以为最后是一个三角形,一条边可以由多个小棒组成,所以想到了状态压缩各种各样的东西,最后成功了……结果发现样例过不了,三条黑线就在我的脑袋上挂着,改正了以后我发现N非常小,想到了回溯每个棍的分组,最多分5组,结果发现超时了……最大是5^12 =  244,140,625,厉害呢…… 后来想贪心,首先想暴力出所有可能的组合,结果发现替换问题是一个难题……最后T T ,我就断片了.. 等看了别人的办法以后,我才发现我忽视了三角形的特性,和把数据排序以后的特点. 如果数据从

Gym 100299C &amp;&amp; UVaLive 6582 Magical GCD (暴力+数论)

题意:给出一个长度在 100 000 以内的正整数序列,大小不超过 10^ 12.求一个连续子序列,使得在所有的连续子序列中, 它们的GCD值乘以它们的长度最大. 析:暴力枚举右端点,然后在枚举左端点时,我们对gcd相同的只保留一个,那就是左端点最小的那个,只有这样才能保证是最大,然后删掉没用的. UVaLive上的数据有问题,比赛时怎么也交不过,后来去别的oj交就过了. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000&qu

UVALive 6511 Term Project

Term Project Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Original ID: 651164-bit integer IO format: %lld      Java class name: Main 解题:强连通分量 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn = 1

UVALive 6508 Permutation Graphs

Permutation Graphs Time Limit: 3000ms Memory Limit: 131072KB This problem will be judged on UVALive. Original ID: 650864-bit integer IO format: %lld      Java class name: Main 解题:逆序数 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long l