• Line of Sight POJ


    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;
    }

     

  • 相关阅读:
    Windows Server 2008 R2域控组策略设置禁用USB
    Windows Server 2008 R2组策略设置计算机配置和用户配置
    Windows Server 2008 R2父域管理员与子域管理员相互登录访问
    转载:如何处理浏览器的断网情况?
    转载:浏览器缓存库设计总结(localStorage/indexedDB)
    手写启动一个本地服务器的命令行工具
    Node.js-核心模块-zlib
    使用console.log打印公司招聘信息和字符画
    转载:准备刷 leetcode 了,才发现自己连时间复杂度都不懂
    转载:前端通信那些事儿
  • 原文地址:https://www.cnblogs.com/Vampire6/p/12230844.html
Copyright © 2020-2023  润新知