Line of Sight POJ - 2074 (线段覆盖 )

Posted vampire6

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Line of Sight POJ - 2074 (线段覆盖 )相关的知识,希望对你有一定的参考价值。

Line of Sight POJ - 2074 

题目链接:https://vjudge.net/problem/POJ-2074

题意:有房子属性线和障碍物,要求你通过属性线能够看到完整房子的最大属性上的距离

思路:

技术图片

 

其实将房子右端点和障碍物左端连线,房子左端点和障碍物右端点连线在属性线上的投影部分就是看不到房子的区域,即图中地下红色部分,那么所求就是途中属性线剩下的蓝色大括号,求其最大值,求解过程中还要注意线段的合并,如果没有障碍物那么就输出属性线的长度就行,如果有一个投影线段完全覆盖了属性线,那么就输出"No View”即可

//
// Created by HJYL on 2020/1/22.
//
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cmath>
using namespace std;
const int maxn=200;
const double eps=1e-8;
struct Point{
    double x,y;
};
int dcmp1(double x)
{
    if (fabs(x)<eps) return 0;
    else return x<0?-1:1;
}
struct segment{
    Point A,B;
};
struct jiao{//投影在属性线上的每一段
    double l,r;
    bool operator<(const jiao &other)const{
        if(this->l==other.l)
            return this->r<other.r;
        return this->l<other.l;
    }
};
double Multi(Point p1, Point p2, Point p0)
{
    return (p1.x - p0.x)*(p2.y - p0.y) - (p2.x - p0.x)*(p1.y - p0.y);
}
double seg_cross(Point a, Point b, Point c, Point d)//直线与线段的交点
{
    Point tmp;
    double s1, s2;
    s1 = Multi(b, c, a);
    s2 = Multi(b, d, a);
    tmp.x = ( s2 * c.x - s1 * d.x ) / (s2 - s1);
    tmp.y = ( s2 * c.y - s1 * d.y ) / (s2 - s1);
    return tmp.x;
}
int main()
{
    segment house;
    while(~scanf("%lf%lf%lf",&house.A.x,&house.B.x,&house.A.y)) {
        if (house.A.x == 0 && house.B.x == 0 && house.A.y == 0)
            break;
        house.B.y = house.A.y;
        segment aim;
        scanf("%lf%lf%lf", &aim.A.x, &aim.B.x, &aim.A.y);
        aim.B.y = aim.A.y;
        int num;
        scanf("%d", &num);
            segment tree[maxn];
            for (int i = 0; i < num; i++) {
                scanf("%lf%lf%lf",&tree[i].A.x,&tree[i].B.x,&tree[i].A.y);
                if(tree[i].A.y>house.A.y||tree[i].A.y<aim.A.y)//障碍物纵坐标大于房子或者小于属性线的均可忽略
                {
                    num--;
                    i--;
                    continue;
                }
                tree[i].B.y=tree[i].A.y;
            }
            if(num==0)//如果没有障碍物那么长度就是线段属性线的长度
            {
                printf("%.2lf
",aim.B.x-aim.A.x);
                continue;
            }
                jiao jj[maxn];
                int ops = 0;
                bool flag=false;
                for (int i = 0; i < num; i++) {
                    jj[ops].l = seg_cross(house.B, tree[i].A, aim.A, aim.B);
                    jj[ops].r = seg_cross(house.A, tree[i].B, aim.A, aim.B);
                    if(jj[ops].l > aim.B.x||jj[ops].r < aim.A.x)//投影下来线段右横坐标小于属性线左边或者投影下来左横坐标大于属性线右边可忽略
                        continue;
                    if(jj[ops].l<aim.A.x&&jj[ops].r>aim.B.x)//障碍物完全挡住了属性线那么就输出"No View"
                    {
                        flag=true;
                        break;
                    }
                    if(jj[ops].l<aim.A.x) jj[ops].l=aim.A.x;//超越属性线的部分端点就按照属性线的端点计算
                    if(jj[ops].r>aim.B.x) jj[ops].r=aim.B.x;
                    ops++;
                }
                if(flag) {
                    printf("No View
");
                    continue;
                }
                sort(jj, jj + ops);//将投影下来的线段排序
                double ll[maxn],rr[maxn];
                ll[0]=jj[0].l,rr[0]=jj[0].r;
                int pos=0;
                for(int i=1;i<ops;i++)//合并这些线段
                {
                    if(rr[pos]>=jj[i].l)
                        rr[pos]=max(rr[pos],jj[i].r);//线段重合
                    else
                    {
                        pos++;
                        ll[pos]=jj[i].l;
                        rr[pos]=jj[i].r;
                    }
                }
                double maxx = max(ll[0] - aim.A.x, aim.B.x - rr[pos]);//将左右两边端点值先比较出来
                for (int i = 0; i < pos; i++) {
                    maxx = max(maxx, ll[i+1]-rr[i]);
                }
                if (dcmp1(maxx) == 1)
                    printf("%.2lf
", maxx);
                else
                    printf("No View
");
    }
    return 0;
}

 

 

 

 

 

以上是关于Line of Sight POJ - 2074 (线段覆盖 )的主要内容,如果未能解决你的问题,请参考以下文章

POJ 2074 Line of Sight 计算几何

[poj] 2074 Line of Sight || 直线相交求交点

Line of Sight 计算几何基础

视距无线传输 (Line of Sight,LOS)

视距无线传输 (Line of Sight,LOS)

POJ 2074 | 线段相交