poj2074 Line of Sight

题目链接: http://poj.org/problem?id=2074

题意:在平面直角坐标上,有一座房子和一些障碍物,还有一条property line,它们都是平行于x轴的线段,若游客站在property line上观看房子,

         求property line上最长的一段,使得游客能够看到房子的全貌。

思路:对每个障碍物,求出它能够挡住游客的那一段,具体方法是:求出房子的右端点与障碍物的左端点连接后与property line的交点的横坐标lview,房子的左端点与障碍物的          右端点连接后与property line的交点的横坐标rviwe,lview和rview之间即为游客被挡住的一段;再按lview从小到大排序后处理,注意property line两端的处理

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

const double eps = 1e-8;

struct Point {
    double x, y;
};

struct Line {
    Point a, b;
} house, pro;

struct Obstruction {
    Point a, b;
    double lview, rview;
};

int dblcmp(double k) {
    if (fabs(k) < eps) return 0;
    return k > 0 ? 1 : -1;
}

double getXByY(Point a, Point b, double y) {
    return (y-a.y)*(a.x-b.x)/(a.y-b.y)+a.x;
}

bool cmp(const Obstruction& obs1, const Obstruction& obs2) {
    return dblcmp(obs1.lview-obs2.lview) <= 0;
}

int main()
{
    double x1, x2, y, tmp, ans;
    int n, i, id, k;

    while (scanf ("%lf%lf%lf", &x1, &x2, &y)) {
        if (!dblcmp(x1) && !dblcmp(x2) && !dblcmp(y)) break;
        house.a.x = x1; house.b.x = x2; house.a.y = house.b.y = y;
        scanf ("%lf%lf%lf\n%d", &pro.a.x, &pro.b.x, &pro.a.y, &n);
        pro.b.y = pro.a.y;
        Obstruction* obs = new Obstruction[n];
        id = 0;
        for (i = 0; i < n; i++) {
            scanf ("%lf%lf%lf", &x1, &x2, &y);
            if (dblcmp(y-house.a.y) >= 0 || dblcmp(y-pro.a.y) <= 0) continue; //不在房子和property line之间的障碍物去掉
            obs[id].a.x = x1;
            obs[id].b.x = x2;
            obs[id].a.y = obs[id].b.y = y;
            obs[id].lview = getXByY(house.b, obs[id].a, pro.a.y); //求出被挡住的最左点
            obs[id].rview = getXByY(house.a, obs[id].b, pro.a.y); //求出被挡住的最右点
            id++;
        }
        sort(obs, obs+id, cmp); //按lview排序
        ans = 0;
        if (dblcmp(obs[0].lview-pro.a.x) > 0) ans = obs[0].lview-pro.a.x; //处理propert line最左边
        if (dblcmp(obs[0].rview-pro.a.x) < 0) obs[0].rview = pro.a.x; //为i==1时求未被挡住长度做准备
        k = 0;  //遍历完前i个障碍物后,挡住最靠右点的障碍物的下标为k
        for (i = 1; i < id; i++) {
            if (dblcmp(obs[k].rview-pro.b.x) >= 0) break; //当求到某一个障碍物时,property line的最右端都被挡住了,直接跳出
            tmp = obs[i].lview-obs[k].rview;
            if (dblcmp(tmp) > 0) {
                k = i;
                if (dblcmp(tmp-ans) > 0) ans = tmp;
            }
            else if (dblcmp(obs[i].rview-obs[k].rview) > 0)  k = i;
        }
        tmp = pro.b.x - obs[k].rview; 
        if (dblcmp(tmp-ans) > 0) ans = tmp; //处理propery line最右端
        if (dblcmp(ans) > 0) printf ("%.2lf\n", ans);
        else printf ("No View\n");
        delete [] obs;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值