POJ 2074 Line of Sight

思路很清晰。


首先排除掉不在house和pro之间的障碍物

然后对每个障碍物,将站在直线上不能看到整个house的区间求出来。

最后对这些区间,扫一遍,贪心求一下即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <map>
#include <sstream>
#include <queue>
#include <vector>
#define MAXN 100005
#define MAXM 211111
#define eps 1e-8
#define INF 50000001
using namespace std;
inline int dblcmp(double d)
{
    if(fabs(d) < eps) return 0;
    return d > eps ? 1 : -1;
}
struct point
{
    double x, y;
    point(){}
    point(double _x, double _y): x(_x), y(_y) {}
    void input()
    {
        scanf("%lf%lf", &x, &y);
    }
    bool operator ==(point a)const
    {
        return dblcmp(a.x - x) == 0 && dblcmp(a.y - y) == 0;
    }
    point sub(point p)
    {
        return point(x - p.x, y - p.y);
    }
    double dot(point p)
    {
        return x * p.x + y * p.y;
    }
    double det(point p)
    {
        return x * p.y - y * p.x;
    }
    double distance(point p)
    {
        return hypot(x - p.x, y - p.y);
    }
}p[5555];
struct line
{
    point a, b;
    line(){}
    line(point _a, point _b){ a = _a; b = _b;}
    void input()
    {
        a.input();
        b.input();
    }
    point crosspoint(line v)
    {
        double a1 = v.b.sub(v.a).det(a.sub(v.a));
        double a2 = v.b.sub(v.a).det(b.sub(v.a));
        return point((a.x * a2 - b.x * a1) / (a2 - a1), (a.y * a2 - b.y * a1) / (a2 - a1));
    }

}house, pro;
bool cmp(point a, point b)
{
    int k = dblcmp(a.x - b.x);
    if(k < 0) return 1;
    else if(k > 0) return 0;
    else return dblcmp(a.y - b.y) < 0;
}
int main()
{
    double xa, ya, xb;
    int m;
    while(scanf("%lf%lf%lf", &xa, &xb, &ya) != EOF)
    {
        if(dblcmp(xa) == 0 && dblcmp(xb) == 0 && dblcmp(ya) == 0) break;
        house = line(point(xa, ya), point(xb, ya));
        scanf("%lf%lf%lf", &xa, &xb, &ya);
        pro = line(point(xa, ya), point(xb, ya));
        scanf("%d", &m);
        int cnt = 0;
        for(int i = 0; i < m; i++)
        {
            scanf("%lf%lf%lf", &xa, &xb, &ya);
            if(dblcmp(ya - house.a.y) >= 0 || dblcmp(ya - pro.a.y) <= 0) continue;
            line tmp = line(point(xa, ya), house.b);
            point p1 = tmp.crosspoint(pro);
            tmp = line(point(xb, ya), house.a);
            point p2 = tmp.crosspoint(pro);
            if(dblcmp(p1.x - pro.b.x) > 0 || dblcmp(p2.x - pro.a.x) < 0) continue;
            p[cnt].x = max(pro.a.x, p1.x);
            p[cnt++].y = min(pro.b.x, p2.x);
        }
        double ans = 0;
        if(cnt)
        {
            sort(p, p + cnt, cmp);
            double lst = pro.a.x;
            for(int i = 0; i < cnt; i++)
            {
                if(dblcmp(p[i].x - lst) > 0) ans = max(ans, p[i].x - lst), lst = p[i].y;
                else if(dblcmp(p[i].y - lst) > 0) lst = p[i].y;
            }
            if(dblcmp(lst - pro.b.x) < 0) ans = max(ans, pro.b.x - lst);
        }
        else ans = pro.b.x - pro.a.x;
        if(dblcmp(ans) == 0) printf("No View\n");
        else printf("%.2f\n", ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值