zoukankan      html  css  js  c++  java
  • 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;
    }

     

  • 相关阅读:
    字节跳动--今日头条iOS客户端启动速度优化
    RSA加密
    几种浏览器
    Linux定时任务crontab无法执行
    Python报错ImportError: No Module Named Typing的解决
    微信小程序:A、B两个小程序相互跳转,出现点击A小程序底部导航栏菜单,第一次点击无法跳转B小程序,需要点击第二次才会触发跳转到B小程序
    c# core 生成随机图文验证码
    携程Apollo统一配置管理中心
    WPF程序中嵌入winForm窗体
    sqlserver 转 postgresql
  • 原文地址:https://www.cnblogs.com/Vampire6/p/12230844.html
Copyright © 2011-2022 走看看