POJ 2074 Line of Sight 直线相交+线段覆盖
2014-11-09 19:48
603 查看
题目描述: http://poj.org/problem?id=2074
题目大意:
从一条路上看路一边的建筑师的家,视线可能会被其他的障碍物挡住(不考虑高度),问从这条路上能看到完整的建筑师的房子的一段路的最大长度。若整条路上都无法看见则输出“No View”, 路、房屋和障碍物都抽象成平行线段。
解题思路:
首先考虑房屋h,和路r,之间的某一条线段p。设p的左端点和h的右端点的连线与r的交点a,p的右端点和h的左端点的连线与r的交点b。容易发现当走在ab之间时视线会被挡住。对于每一条线段都可以尝试求出覆盖在r上的“盲区“ab。相当于线段覆盖,而我们只要求出不被覆盖的最大长度就好了。注意有的线段形成的盲区可能不在线段r上或者有一端不在r上,需要特殊判断。
以上考虑的是在h和r之间的线段,题目只说了障碍物不会与h和r相交,但可能在h与r之间的区域外。这种情况下障碍物不会对视线产生影响,但是用以上的方法可能计算出在r上的交点,造成WA。所以读入的时候判断一下,如果不在h与r之间直接忽视掉。
剩下的就是怎么计算最大不被覆盖的线段的问题。我们可以先把所有盲区线段以左端点坐标为关键字从小到大排序,然后从左到右扫一遍,一边维护i之前所有线段的最右端的x坐标lastX。如果第i个盲区的左端点大于lastX,那么lastX到i的左端点的这片区域都是不被覆盖的。扫描每个线段时更新lastX。r的左右端点需要特别判断一下。
复杂度:
计算盲区O(n),计算最大长度O(n)。复杂度O(n)。
题目大意:
从一条路上看路一边的建筑师的家,视线可能会被其他的障碍物挡住(不考虑高度),问从这条路上能看到完整的建筑师的房子的一段路的最大长度。若整条路上都无法看见则输出“No View”, 路、房屋和障碍物都抽象成平行线段。
解题思路:
首先考虑房屋h,和路r,之间的某一条线段p。设p的左端点和h的右端点的连线与r的交点a,p的右端点和h的左端点的连线与r的交点b。容易发现当走在ab之间时视线会被挡住。对于每一条线段都可以尝试求出覆盖在r上的“盲区“ab。相当于线段覆盖,而我们只要求出不被覆盖的最大长度就好了。注意有的线段形成的盲区可能不在线段r上或者有一端不在r上,需要特殊判断。
以上考虑的是在h和r之间的线段,题目只说了障碍物不会与h和r相交,但可能在h与r之间的区域外。这种情况下障碍物不会对视线产生影响,但是用以上的方法可能计算出在r上的交点,造成WA。所以读入的时候判断一下,如果不在h与r之间直接忽视掉。
剩下的就是怎么计算最大不被覆盖的线段的问题。我们可以先把所有盲区线段以左端点坐标为关键字从小到大排序,然后从左到右扫一遍,一边维护i之前所有线段的最右端的x坐标lastX。如果第i个盲区的左端点大于lastX,那么lastX到i的左端点的这片区域都是不被覆盖的。扫描每个线段时更新lastX。r的左右端点需要特别判断一下。
复杂度:
计算盲区O(n),计算最大长度O(n)。复杂度O(n)。
<span style="font-family:Microsoft YaHei;font-size:12px;">/* * 2014.11.09 * Problem: 2074 * Memory: 192K Time: 0MS * Language: C++ Result: Accepted * */ #include <iostream> #include <algorithm> #include <cmath> #define EPS 1e-8 #define MAXN 107 using namespace std; struct Event { double x1, x2; }v[MAXN<<2]; int n, vn; double hx1, hx2, hy, rx1, rx2, ry; bool compare(struct Event a, struct Event b) { return a.x1<b.x1; } double getEventX(double x1, double y1, double x2, double y2) { return x1 - (y1-ry)*(x2-x1)/(y2-y1); } double max(double a, double b) {return a>b?a:b;} double min(double a, double b) {return a>b?b:a;} void init() { double v1, v2, x1, x2, y; vn = 0; scanf("%d", &n); for (int i=1; i<=n; i++) { scanf("%lf %lf %lf", &x1, &x2, &y); if (y >= hy || y <= ry) continue; v1 = getEventX(x1, y, hx2, hy); v2 = getEventX(x2, y, hx1, hy); if (v2-rx1<=EPS || v1-rx2>=-EPS) continue; vn++; v[vn].x1 = max(v1, rx1); v[vn].x2 = min(v2, rx2); } } int main() { scanf("%lf %lf %lf", &hx1, &hx2, &hy); while (hy!=0 && hx1!=0 && hx2!=0) { scanf("%lf %lf %lf", &rx1, &rx2, &ry); init(); sort(v+1, v+1+vn, compare); double length=0, lastX=0;; for (int i=1;i<=vn;i++) { if (v[i].x1>lastX) { length = max(length, v[i].x1-lastX); lastX = v[i].x2; } else { lastX = max(lastX, v[i].x2); } } length = max(length, rx2 - lastX); if (fabs(length)<EPS) { printf("No View\n"); } else { printf("%.2lf\n", length); } scanf("%lf %lf %lf", &hx1, &hx2, &hy); } return 0; }</span></span></span></span>
相关文章推荐
- poj 2074 Line of Sight(视线问题,求直线与线段的交点及判断相交)
- POJ 2074 Line of Sight(判线段与直线相交)
- [poj] 2074 Line of Sight || 直线相交求交点
- 简单几何(直线求交点) POJ 2074 Line of Sight
- POJ 2074 Line of Sight 直线交
- POJ 2074 Line of Sight 直线交
- POJ 2074 Line of Sight
- Poj 2074 Line of Sight
- POJ 2074 Line of Sight 计算几何
- poj 2074 Line of Sight
- POJ 2074 Line of Sight
- Poj 2074 Line of Sight
- poj 2074 Line of Sight(计算几何)
- poj 2074 Line of Sight
- POJ 2074 Line of Sight(求交点)
- poj 2074 Line of Sight
- poj 2074 Line of Sight (计算几何,细节题)
- POJ 2074 Line of Sight
- POJ 2074 Line of Sight
- poj 2074 Line of Sight