POJ 2074 Line of Sight

来源:互联网 发布:数据挖掘预处理技术 编辑:程序博客网 时间:2024/06/01 11:35

题目大意:

        一座房子、一条马路,中间隔着几个障碍物,他们都可以看做线段,并且都平行于x轴,都具有一定长度,现在要求在马路上可以看到整个房子的最长的连续的一段长度。

        现有多个测例,每个测例中先给出房子左右两点的x坐标以及一个y坐标(以0 0 0作为输入的结束),接着给出马路左右两点的x坐标以及一个y坐标,接着给出一共有多上障碍物n(int型正整数),以及每个障碍物的左右端点的x坐标和一个y坐标,题中保证所有的x1、x2都有x1 < x2,并且 y房子 > y马路,障碍物位于房子和马路之间,就算和房子同样高,也不会和房子重合,其中所有的坐标输入都是实数(用double表示),对于每个测例,如果存在该最长连续线段则输出其长度(精确到小数点后两位),否则就输出“No View"。

题目链接

注释代码:

/*       * Problem ID : POJ 2074 Line of Sight * Author     : Lirx.t.Una       * Language   : C++      * Run Time   : 0 ms       * Run Memory : 244 KB      */#include <algorithm>#include <iostream>#include <string.h>#include <cstdio>#include <cmath>#defineEPS1E-8//maximum number of obstacles//测试过的障碍物的最小数量#defineMAXOBN15using namespace std;intsgn(double x) {//sign//用于判定浮点数的符号和比较两个浮点数的大小//sgn(a, b)   == 0相等,> 0就是a > b,< 0表示a < b//直接用比较符操作时CPU是比较每一位的,往往不精确//比如3.0有时候小数点后9、10位会是一个1、2、3之类的数字导致结果误差if ( fabs(x) < EPS )return 0;return x > 0 ? 1 : -1;}structPoint {//点doublex, y;Point(void) {}Point( double xx, double yy ) :x(xx), y(yy) {}friend double//计算直线ab和与x轴平行的直线y的交点的横坐标    //注意采用值传递xByY( Point a, Point b, double y ) {return ( y - a.y ) * ( a.x - b.x ) / ( a.y - b.y ) + a.x;}};structLine {//和x轴平行的直线doublex1, x2;//左右端点横坐标doubley;//直线的纵坐标Line(void) {}friend istream &//输入operator>>( istream &is, Line &l ) {is >> l.x1 >> l.x2 >> l.y;return is;}boolempty(void) {//判空,如果为空表示输入的结束return !sgn(x1) && !sgn(x2) && !sgn(y);}};//视线//表示某个障碍物阻挡住整个房子的范围//lft和rht分别表示这个阻挡范围的左右端点的横坐标//lft为障碍物左端点和房子右端点的连线在马路上的交点的横坐标//rht为障碍物右端点和房子左端点的连线在马路上的交点的横坐标structView {double lft, rht;};boolfcmp(const View &v1, const View &v2) {//对障碍物视线按照lft值从小到大排列return sgn( v1.lft - v2.lft ) <= 0;}Linehs;//house,房子Linepl;//property line,马路Viewv[MAXOBN];//view,v[i]表示i号障碍物的遮挡范围,下标从0计intmain() {intn;//障碍物总数intnb;//number of final obstacle,最终确定下来的符合“要求”的障碍物数量//那些在马路和房子两边的障碍物将被舍弃,即剪枝inti;//计数变量intrm;//right most obstacle,当前rht值最大的障碍物的序号doubleans;//保存最终结果,即可见范围的最大长度doubletmp;//临时变量Lineob;//obstacle,用于临时存放输入的障碍物while ( cin >> hs, !hs.empty() ) {//输入房子并判空//由于浮点数精度问题,虽然下一个测例能完全覆盖上一个测例//但是还是需要清零以防止位置的精度误差//词句不写为蛋疼的WA的!!!memset(v, 0, sizeof(v));cin >> pl >> n;//输入马路和障碍物总数//计算障碍物的遮挡范围并剔除不符合要求的障碍物nb = 0;while ( n-- ) {cin >> ob;if ( sgn( ob.y - hs.y ) >= 0 || sgn( ob.y - pl.y ) <= 0 )//剪枝1continue;//在房子和马路之外的范围//计算遮挡范围v[nb].lft = xByY( Point( hs.x2, hs.y ), Point( ob.x1, ob.y ), pl.y );v[nb].rht = xByY( Point( hs.x1, hs.y ), Point( ob.x2, ob.y ), pl.y );nb++;}sort(v, v + nb, fcmp);//将视线按照lft从小到大排列ans = 0;//处理左边界//0的左边界大于马路左边界,这就意味着pl.x1 ~ v[0].lft之间是可见的,可以用来初始化ansif ( sgn( v[0].lft - pl.x1 ) > 0 ) ans = v[0].lft - pl.x1;//0的右边界竟然在马路左边界左边,这就意味着0完全不能阻挡房子,因此不妨将0的右边界设为马路左边界if ( sgn( v[0].rht - pl.x1 ) < 0 ) v[0].rht = pl.x1;//其余情况就是0左边界小于马路左边界但0的右边界大于马路右边界,此种情况下0的rht仍然是当前最大的//因此不需做任何操作//rm的初始化//如果rm的右边界超出马路右边界就以为着后面还没被检查的障碍物的阻挡范围都被rm覆盖了//因为rm在前面(lft比后面的都小),因此可以直接退出循环for ( rm = 0, i = 1; i < nb && sgn( v[rm].rht - pl.x2 ) < 0; i++ ) {//剪枝2if ( sgn( tmp = v[i].lft - v[rm].rht ) > 0 ) {//i左边界大于rm右边界//这就意味着v[rm].rht ~ v[i].lft之间的范围是可见的,需要比较和ans的优劣rm = i;//i的右边界一定大于rm的rht,因此需要更新rmif ( sgn( tmp - ans ) > 0 )ans = tmp;}//另一种情况就是i的左边界小于rm的右边界,这就意味着有重叠else if ( sgn( v[i].rht - v[rm].rht ) > 0 )//但是如果i的rht大于rm的rhtrm = i;//则当前最大的rht为i的rht,需要覆盖//剩余的情况是i完全被rm覆盖,因此什么都不用做,直接检测下一个障碍物}tmp = pl.x2 - v[rm].rht;//检查右边界if ( sgn( tmp - ans ) > 0 )ans = tmp;if ( sgn(ans) > 0 )//表示存在最长可见区printf("%.2lf\n", ans);else//ans = 0.0,不存在完全可见区puts("No View");}return 0;}

无注释代码:

#include <algorithm>#include <iostream>#include <string.h>#include <cstdio>#include <cmath>#defineEPS1E-8#defineMAXOBN15using namespace std;intsgn(double x) {if ( fabs(x) < EPS )return 0;return x > 0 ? 1 : -1;}structPoint {doublex, y;Point(void) {}Point( double xx, double yy ) :x(xx), y(yy) {}friend doublexByY( Point a, Point b, double y ) {return ( y - a.y ) * ( a.x - b.x ) / ( a.y - b.y ) + a.x;}};structLine {doublex1, x2;doubley;Line(void) {}friend istream &operator>>( istream &is, Line &l ) {is >> l.x1 >> l.x2 >> l.y;return is;}boolempty(void) {return !sgn(x1) && !sgn(x2) && !sgn(y);}};structView {double lft, rht;};boolfcmp(const View &v1, const View &v2) {return sgn( v1.lft - v2.lft ) <= 0;}Linehs;Linepl;Viewv[MAXOBN];intmain() {intn;intnb;inti;intrm;doubleans;doubletmp;Lineob;while ( cin >> hs, !hs.empty() ) {memset(v, 0, sizeof(v));cin >> pl >> n;nb = 0;while ( n-- ) {cin >> ob;if ( sgn( ob.y - hs.y ) >= 0 || sgn( ob.y - pl.y ) <= 0 )continue;v[nb].lft = xByY( Point( hs.x2, hs.y ), Point( ob.x1, ob.y ), pl.y );v[nb].rht = xByY( Point( hs.x1, hs.y ), Point( ob.x2, ob.y ), pl.y );nb++;}sort(v, v + nb, fcmp);ans = 0;if ( sgn( v[0].lft - pl.x1 ) > 0 ) ans = v[0].lft - pl.x1;if ( sgn( v[0].rht - pl.x1 ) < 0 ) v[0].rht = pl.x1;for ( rm = 0, i = 1; i < nb && sgn( v[rm].rht - pl.x2 ) < 0; i++ ) {if ( sgn( tmp = v[i].lft - v[rm].rht ) > 0 ) {rm = i;if ( sgn( tmp - ans ) > 0 )ans = tmp;}else if ( sgn( v[i].rht - v[rm].rht ) > 0 )rm = i;}tmp = pl.x2 - v[rm].rht;if ( sgn( tmp - ans ) > 0 )ans = tmp;if ( sgn(ans) > 0 )printf("%.2lf\n", ans);elseputs("No View");}return 0;}

单词解释:

architect:n, 建筑师

sight:n, 视觉,视力,景象

property:n, 财产,所有权

shrub:n, 灌木丛

hedge:n, 树篱笆

obstruction:n, 障碍物

block:vt, 阻塞,阻碍

portion:n, 部分

landscape:n, 风景,风景画

architecture:n, 建筑学,建筑风格

0 0
原创粉丝点击