POJ2074 Line of Sight

原题传送门:http://poj.org/problem?id=2074
博主的中文题面(坑爹POJ):
https://www.luogu.org/problemnew/show/T22869

Line of Sight

Description

An architect is very proud of his new home and wants to be sure it can be seen by people passing by his property line along the street. The property contains various trees, shrubs, hedges, and other obstructions that may block the view. For the purpose of this problem, model the house, property line, and obstructions as straight lines parallel to the x axis:

To satisfy the architect’s need to know how visible the house is, you must write a program that accepts as input the locations of the house, property line, and surrounding obstructions and calculates the longest continuous portion of the property line from which the entire house can be seen, with no part blocked by any obstruction.

Input

Because each object is a line, it is represented in the input file with a left and right x coordinate followed by a single y coordinate:
< x1 > < x2 > < y >
Where x1, x2, and y are non-negative real numbers. x1 < x2
An input file can describe the architecture and landscape of multiple houses. For each house, the first line will have the coordinates of the house. The second line will contain the coordinates of the property line. The third line will have a single integer that represents the number of obstructions, and the following lines will have the coordinates of the obstructions, one per line.
Following the final house, a line “0 0 0” will end the file.
For each house, the house will be above the property line (house y > property line y). No obstruction will overlap with the house or property line, e.g. if obstacle y = house y, you are guaranteed the entire range obstacle[x1, x2] does not intersect with house[x1, x2].

Output

For each house, your program should print a line containing the length of the longest continuous segment of the property line from which the entire house can be to a precision of 2 decimal places. If there is no section of the property line where the entire house can be seen, print “No View”.

Sample Input

2 6 6
0 15 0
3
1 2 1
3 4 1
12 13 1
1 5 5
0 10 0
1
0 15 1
0 0 0

Sample Output

8.80
No View

题目大意

在二维平面中有多条平行与x轴的线段,求其中某一条线段(路)上能完整看到另一条线段(房子)的最长连续线段的长度。

题解

我们可以先求出所有盲区,按左端点从小到大排序,最后从左到右扫描一波,不断更新最大非盲区的值并合并盲区。    
关于盲区的求解,只需要将房子的左右端点分别与障碍物右左端点连接(注意顺序),做出直线求解其与路的交点就行了。

障碍物不一定在房子和道路中间,需要特判甩到一个很远的地方。障碍物不会和房子重合,但是可能共线,需要特判。  
另外,博主的代码C++ AC,G++ WA,不知道为什么(黑人问号)。

代码
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define db double
using namespace std;
const db eps=1e-8;
const int inf=-1e9;
struct pt{db x,y;};
int sig(db a){return (a>eps)-(a<-eps);}
db inter(db a1,db a2,db b1,db b2,db c1,db c2,db d1,db d2)
{
    if(!sig(a1-b1)) return a1;
    db k=(b2-a2)/(b1-a1);
    return (a2-c2-k*a1)/(-k);
}
struct sd{
    db le,ri;
    bool operator < (const sd &a) const
    {
        return le<a.le;
    }
};
sd bli[110];
pt hle,hri;
db lmax,rmax,low;
int m;
db hh(db a)
{
    if(a<lmax) return lmax;
    return a<rmax?a:rmax;
}
void work(db a,db b,db c,int p)
{
    if(sig(hle.y-c)<=0||sig(c-low)<0) a=b=c=-inf;
    bli[p].le=hh(inter(a,c,hri.x,hri.y,lmax,low,rmax,low));
    bli[p].ri=hh(inter(b,c,hle.x,hle.y,lmax,low,rmax,low));
}
void in()
{
    if(!hle.x&&!hri.x&&!hle.y) exit(0);
    scanf("%lf%lf%lf%d",&lmax,&rmax,&low,&m);
    hri.y=hle.y;
    db a,b,c;
    for(int i=1;i<=m;++i)
    scanf("%lf%lf%lf",&a,&b,&c),work(a,b,c,i);
}
void ac()
{
//  printf("---------\n");
//  for(int i=1;i<=m;++i)
//  printf("%.2lf %.2lf\n",bli[i].le,bli[i].ri);
//  printf("---------\n");
    sort(bli+1,bli+1+m);
    bli[0].le=bli[0].ri=lmax;
    bli[m+1].le=bli[m+1].ri=rmax;
    m+=1;
    db ans=-1.0,p2=bli[0].ri;
    for(int i=1;i<=m;++i)
    {
        if(bli[i].le>p2) ans=max(ans,bli[i].le-p2);
        p2=max(p2,bli[i].ri);
    }
    if(sig(ans)>0) printf("%.2lf\n",ans);
    else printf("No View\n");
    memset(bli,0,sizeof(bli));
}
int main()
{
//  freopen("data.out","w",stdout);
    while(scanf("%lf%lf%lf",&hle.x,&hri.x,&hle.y)==3)
    {
        in();ac();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值