地址:http://poj.org/problem?id=2074

题目:

Line of Sight
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 4148   Accepted: 1291

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
思路:首先排除掉不在house和proprety line的y的区间中线段,再求出对于每个线段的在property上的不可见区间。
  如图所示:

然后把所有的区间按左端点为第一关键字,右端点为第二关键字从小到大排序,扫描一遍就好了。

 /* 二维几何  */
/* 需要包含的头文件 */
#include<cstdio>
#include <cstring>
#include <cmath >
#include <iostream>
#include <algorithm> using namespace std;
/** 常用的常量定义 **/
const double INF = 1e200;
const double eps = 1e-;
const double PI = acos(-1.0);
const int Max = 1e5;
/** 基本几何结构 **/
struct Point
{
double x,y;
Point(double a=, double b=){x=a,y=b;}
bool operator<(const Point &ta)const
{
if(x==ta.x) return y<ta.y;
return x<ta.x;
}
friend Point operator+(const Point &ta,const Point &tb)
{
return Point(ta.x+tb.x,ta.y+tb.y);
}
friend Point operator-(const Point &ta,const Point &tb)
{
return Point(ta.x-tb.x,ta.y-tb.y);
}
};
struct Vec2D ///二维向量,*重载为点乘,/重载为叉乘
{
double x,y;
Vec2D(double ta,double tb){x=ta,y=tb;}
Vec2D(Point &ta){x=ta.x,y=ta.y;}
friend double operator*(const Vec2D &ta,const Vec2D &tb)
{
return ta.x*tb.x+ta.y*tb.y;
}
friend double operator/(const Vec2D &ta,const Vec2D &tb)
{
return ta.x*tb.y-ta.y*tb.x;
}
friend Vec2D operator+(const Vec2D &ta,const Vec2D &tb)
{
return Vec2D(ta.x+tb.x,ta.y+tb.y);
}
friend Vec2D operator-(const Vec2D &ta,const Vec2D &tb)
{
return Vec2D(ta.x-tb.x,ta.y-tb.y);
}
Vec2D operator=(const Vec2D &ta)
{
x=ta.x,y=ta.y;
return *this;
}
};
struct LineSeg ///线段,重载了/作为叉乘运算符,*作为点乘运算符
{
Point s,e;
LineSeg(){s=Point(,),e=Point(,);}
LineSeg(Point a, Point b){s=a,e=b;}
double lenth(void)
{
return sqrt((s.x-e.x)*(s.x-e.x)+(s.y-e.y)*(s.y-e.y));
}
friend double operator*(const LineSeg &ta,const LineSeg &tb)
{
return (ta.e.x-ta.s.x)*(tb.e.x-tb.s.x)+(ta.e.y-ta.s.y)*(tb.e.y-tb.s.y);
}
friend double operator/(const LineSeg &ta,const LineSeg &tb)
{
return (ta.e.x-ta.s.x)*(tb.e.y-tb.s.y)-(ta.e.y-ta.s.y)*(tb.e.x-tb.s.x);
}
LineSeg operator=(const LineSeg &ta)
{
s=ta.s,e=ta.e;
return *this;
}
};
struct Line /// 直线的解析方程 a*x+b*y+c=0 为统一表示,约定 a >= 0
{
double a,b,c;
Line(double d1=, double d2=-, double d3=){ a=d1,b=d2,c=d3;}
}; int sgn(double ta,double tb);
double fArea(Point &ta,Point &tb,Point &tc);
bool intersect(LineSeg &lx,LineSeg &ly);
bool intersection(LineSeg &lx,LineSeg &ly,Point &pt);
double getdis(const Point &ta,const Point &tb);
bool cmp(const Point &ta,const Point &tb);
void graham(Point ps[],Point tb[],int n,int &num);
void ConvexClosure(Point ps[],Point tb[],int n,int &num); void scf(LineSeg &lx)
{
cin>>lx.s.x>>lx.e.x>>lx.s.y;
lx.e.y=lx.s.y;
}
LineSeg hs,pl,cur,lx;
Point line[Max],tx,ty;
int main(void)
{
while()
{
int n,num=;
scf(hs);
if(!(hs.s.x||hs.s.y||hs.e.x))
break;
scf(pl);
cin>>n;
for(int i=;i<n;i++)
{
scf(cur);
if(sgn(cur.s.y,hs.s.y)<&&sgn(cur.s.y,pl.s.y)>)
{
lx=LineSeg(hs.s,cur.e);
intersection(lx,pl,tx);
lx=LineSeg(hs.e,cur.s);
intersection(lx,pl,ty);
if(tx.x>=ty.x)
line[num++]=Point(ty.x,tx.x);
else
line[num++]=Point(tx.x,ty.x);
}
}
sort(line,line+num);
double ans=,rr=pl.s.x;
line[num++]=Point(pl.e.x,pl.e.x);
for(int i=;i<num;i++)
if(!(line[i].y<pl.s.x || line[i].x>pl.e.x))
{
//printf("====%f %f\n",line[i].x,line[i].y);
line[i].x=max(pl.s.x,line[i].x);
line[i].y=min(pl.e.x,line[i].y);
if(line[i].x>rr)
ans=max(ans,line[i].x-rr);
rr=max(line[i].y,rr);
}
if(sgn(ans,))
printf("%.2f\n",ans);
else
printf("No View\n"); } return ;
} /*******判断ta与tb的大小关系*******/
int sgn(double ta,double tb)
{
if(fabs(ta-tb)<eps)return ;
if(ta<tb) return -;
return ;
}
/*********求两点的距离*************/
double getdis(const Point &ta,const Point &tb)
{
return sqrt((ta.x-tb.x)*(ta.x-tb.x)+(ta.y-tb.y)*(ta.y-tb.y));
}
/************三角形面积**************************/
double fArea(Point &ta,Point &tb,Point &tc)
{
return fabs(LineSeg(ta,tb)/LineSeg(ta,tc)*0.5);
} /*********** 判断P1P2是否和P3P4相交****************************
其中Pi坐标为(xi,yi),需要满足两个条件:
(1)快速排斥试验:
以P1P2为对角线的矩形S1是否和以P3P4为对角线的矩形S2相交,
即 min(x1,x2)<=max(x3,x4) && min(x3,x4)<=max(x1,x2)
&& min(y1,y2)<=max(y3,y4) &&min(y3,y4)<=max(y1,y2)
(2)跨立试验:
点P1,P2必然在线段P3P4的不同侧,
点P3,P4必然在线段P1P2的不同侧,
***************************************************************/
bool intersect(LineSeg &lx,LineSeg &ly)
{
return sgn(min(lx.s.x,lx.e.x),max(ly.s.x,ly.e.x))<=
&& sgn(min(ly.s.x,ly.e.x),max(lx.s.x,lx.e.x))<=
&& sgn(min(lx.s.y,lx.e.y),max(ly.s.y,ly.e.y))<=
&& sgn(min(ly.s.y,ly.e.y),max(lx.s.y,lx.e.y))<=
&& sgn((lx/LineSeg(lx.s,ly.s))*(lx/LineSeg(lx.s,ly.e)),)<=
&& sgn((ly/LineSeg(ly.s,lx.s))*(ly/LineSeg(ly.s,lx.e)),)<=;
}
/************线段求交点**************************
返回-1代表直线平行,返回0代表直线重合,返回1代表线段相交
利用叉积求得点P分线段DC的比,
然后利用高中学习的定比分点坐标公式求得分点P的坐标
**************************************************/
bool intersection(LineSeg &lx,LineSeg &ly,Point &pt)
{
pt=lx.s;
if(sgn(lx/ly,)==)
{
if(sgn(LineSeg(lx.s,ly.e)/ly,)==)
return ;//重合
return -;//平行
}
double t = (LineSeg(lx.s,ly.s)/ly)/(lx/ly);
pt.x+=(lx.e.x-lx.s.x)*t, pt.y+=(lx.e.y-lx.s.y)*t;
return ;
}
/** ************凸包算法****************
寻找凸包的graham 扫描法
PS(PointSet)为输入的点集;
tb为输出的凸包上的点集,按照逆时针方向排列;
n为PointSet中的点的数目
num为输出的凸包上的点的个数
****************************************** **/
bool cmp(const Point &ta,const Point &tb)/// 选取与最后一条确定边夹角最小的点,即余弦值最大者
{
// double tmp=LineSeg(ps[0],ta)/LineSeg(ps[0],tb);
// if(sgn(tmp,0)==0)
// return getdis(ps[0],ta)<getdis(ps[0],tb);
// else if(tmp>0)
// return 1;
return ;
}
void graham(Point ps[],Point tb[],int n,int &num)
{
int cur=,top=;
for(int i=;i<n;i++)
if(sgn(ps[cur].y,ps[i].y)> || (sgn(ps[cur].y,ps[i].y)== && sgn(ps[cur].x,ps[i].x)>))
cur=i;
swap(ps[cur],ps[]);
sort(ps+,ps+n,cmp);
tb[]=ps[],tb[]=ps[],tb[]=ps[];
for(int i=;i<n;i++)
{
while(sgn(LineSeg(tb[top-],tb[top])/LineSeg(tb[top-],ps[i]),)<)
top--;
tb[++top]=ps[i];
}
num=top+;
}
/** 卷包裹法求点集凸壳,参数说明同graham算法 **/
void ConvexClosure(Point ps[],Point tb[],int n,int &num)
{
LineSeg lx,ly;
int cur,ch;
bool vis[Max];
num=-,cur=;
memset(vis,,sizeof(vis));
for(int i=;i<n;i++)
if(sgn(ps[cur].y,ps[i].y)> || (sgn(ps[cur].y,ps[i].y)== && sgn(ps[cur].x,ps[i].x)>))
cur=i;
tb[++num]=ps[cur];
lx.s=Point(ps[cur].x-,ps[cur].y),lx.e=ps[cur];
/// 选取与最后一条确定边夹角最小的点,即余弦值最大者
while()
{
double mxcross=-,midis,tmxcross;
ly.s=lx.e;
for(int i=;i<n;i++)if(!vis[i])
{
ly.e=ps[i];
tmxcross=(lx*ly)/lx.lenth()/ly.lenth();
if(sgn(tmxcross,mxcross)> ||(sgn(tmxcross,mxcross)== && getdis(ly.s,ly.e)<midis))
mxcross=tmxcross,midis=getdis(ly.s,ly.e),ch=i;
}
if(ch==cur)break;
tb[++num]=ps[ch],vis[ch]=;
lx.s=tb[num-],lx.e=tb[num],ly.s=tb[num];
}
}
 

Poj 2074 Line of Sight的更多相关文章

  1. 简单几何(直线求交点) POJ 2074 Line of Sight

    题目传送门 题意:从一条马路(线段)看对面的房子(线段),问连续的能看到房子全部的最长区间 分析:自己的思路WA了:先对障碍物根据坐标排序,然后在相邻的障碍物的间隔找到区间,这样还要判断是否被其他障碍 ...

  2. poj 2074 Line of Sight 计算几何

    /** 大意:给定一个建筑--水平放置,给定n个障碍物, 给定一条街道,从街道上能看到整个建筑的最长的连续的区域 思路: 分别确定每一个障碍物所确立的盲区,即----建筑物的终点与障碍物的起点的连线, ...

  3. [poj] 2074 Line of Sight || 直线相交求交点

    原题 给出一个房子(线段)的端点坐标,和一条路的两端坐标,给出一些障碍物(线段)的两端坐标.问在路上能看到完整房子的最大连续长度是多长. 将障碍物按左端点坐标排序,然后用房子的右端与障碍物的左端连线, ...

  4. unity下的Line of Sight(LOS)的绘制

    先说说什么是Linf of Sight.在很多RTS游戏中,单位与单位之间的视野关系经常会受到障碍物遮挡.Line of Sight指的就是两个物体之间是否没有障碍物遮挡. 比如在dota中,玩家的视 ...

  5. 【转】Using Raycasts and Dynamically Generated Geometry to Create a Line of Sight on Unity3D

    http://www.linkedin.com/pulse/using-raycasts-dynamically-generated-geometry-create-line-thomas José ...

  6. 【转】unity下的Line of Sight(LOS)的绘制

    http://www.cnblogs.com/yangrouchuan/p/6366629.html 先说说什么是Linf of Sight.在很多RTS游戏中,单位与单位之间的视野关系经常会受到障碍 ...

  7. POJ2074:Line of Sight——题解

    http://poj.org/problem?id=2074 题目大意:(下面的线段都与x轴平行)给两条线段,一个点在其中一条线段看另一条线段,但是中间有很多线段阻挡视线.求在线段上最大连续区间使得在 ...

  8. G - Line of Sight

    来源poj2074 An architect is very proud of his new home and wants to be sure it can be seen by people p ...

  9. poj 2074

    哎怎么说,感觉现在处理平面上点线的题已经比较熟练了. 这题就离散化然后搞个前缀和就没了. 准备开始进一步的自闭了. 下面是disguss的一些样例... 其实是我自己写错了个地方,本来能1A的. #i ...

随机推荐

  1. [Buzz Today]2013.08.18

    # Go 语言实现memcached:groupcache memcached作者Brad Fitzpatrick用Go语言重新实现了memcached. groupcache继承了memcached ...

  2. Hibernate Tools插件的使用

            Hibernate Tools是由JBoss推出的一个Eclipse综合开发工具插件,该插件可以简化ORM框架Hibernate,以及JBoss Seam,EJB3等的开发工作.Hib ...

  3. markDownPad Key

    邮箱: Soar360@live.com 授权秘钥: GBPduHjWfJU1mZqcPM3BikjYKF6xKhlKIys3i1MU2eJHqWGImDHzWdD6xhMNLGVpbP2M5SN6b ...

  4. ROS导航之参数配置和自适应蒙特卡罗定位

    我们的机器人使用两种导航算法在地图中移动:全局导航(global)和局部导航(local).这些导航算法通过代价地图来处理地图中的各种信息,导航stack使用两种costmaps http://www ...

  5. java 连接mariadb 无法获取数据源的问题,在ubuntu上部署的时候(原创)

    问题: 连接数据库时报错: log4j:WARN No appenders could be found for logger (com.mchange.v2.log.MLog).log4j:WARN ...

  6. 在UI线程之外,多线程处理Bitmaps

    多线程处理Bitmaps     上一篇,我们讨论了:Android有效的处理Bitmap,降低内存 ,可是最好不要运行在主线程(UI线程),假设图片是本地的或者网络的又或者是其它地方的. 图片载入的 ...

  7. spring 项目升级到spring cloud记录 数据源配置

    用的阿里的数据源  增加pom <dependency> <groupId>com.alibaba</groupId> <artifactId>drui ...

  8. Java中匿名内部类

    匿名内部类也就是没有名字的内部类 正因为没有名字,所以匿名内部类只能使用一次,它通常用来简化代码编写 但使用匿名内部类还有个前提条件:必须继承一个父类或实现一个接口 实例1:不使用匿名内部类来实现抽象 ...

  9. 基础知识《十四》Java异常的栈轨迹fillInStackTrace和printStackTrace的用法

    本文转自wawlian 捕获到异常时,往往需要进行一些处理.比较简单直接的方式就是打印异常栈轨迹Stack Trace.说起栈轨迹,可能很多人和我一样,第一反应就是printStackTrace()方 ...

  10. git 拉取远程分支到本地并建立关联关系

    git拉取远程分支到本地   一.查看远程分支 使用如下git命令查看所有远程分支: git branch -r   二.拉取远程分支并创建本地分支 方法一 使用如下命令: git checkout ...