题目大意:有一个不反光并且不透光的管道,现在有一束光线从最左端进入,问能达到的最右端是多少,输出x坐标。
 
分析:刚开始做是直接枚举两个点然后和管道进行相交查询,不过这样做需要考虑的太多,细节不容易掌控。后来发现其实只需要对接口进行一下相交查询就简单多了,因为只需要考虑能不能通过每个截口就可以了,而且这样做的好处还有没有平行线和重叠线的情况,因为所有的截口都是垂直于x轴的,换一种想法海阔太空啊。
 
代码如下:
==========================================================================================================================
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std; const int MAXN = ;
const double EPS = 1e-;
const double oo = 1e9+; int Sign(double t)
{
if(t > EPS)return ;
if(fabs(t)<EPS)return ;
return -;
} struct Point
{
double x, y;
Point(double x=, double y=):x(x), y(y){}
Point operator - (const Point &t)const{
return Point(x-t.x, y-t.y);
}
double operator ^(const Point &t)const{
return x*t.y - y*t.x;
}
bool operator == (const Point &t)const{
return fabs(x-t.x)<EPS && fabs(y-t.y)<EPS;
}
};
struct Segment
{
Point S, E;
double a, b, c;///ax + by = c; Segment(Point S=, Point E=):S(S),E(E){
///求线段所在的直线的常数项
a = S.y - E.y;
b = E.x - S.x;
c = E.x*S.y - S.x*E.y;
}
bool Inters(const Segment &tmp) const{
int t1 = Sign((S-E)^(tmp.S-E));
int t2 = Sign((S-E)^(tmp.E-E));
///不存在平行,或者共线情况,有一点相交都算相交
if(t1+t2== || t1+t2==-)
return false;
else
return true;
}
Point crossNode(const Segment &tmp)const{
///求交点
Point t;
t.x = (c*tmp.b-tmp.c*b) / (a*tmp.b-tmp.a*b);
t.y = (c*tmp.a-tmp.c*a) / (b*tmp.a-tmp.b*a); return t;
}
void MakeNewSeg(double Lx, double Rx)
{///构造新的线段,与原来的线段共线
S.x = Lx, S.y = (c-a*Lx) / b;
E.x = Rx, E.y = (c-a*Rx) / b;
}
}; double FindMinX(Segment s, Segment sg[], int N)
{
double ans=oo; for(int i=; i<N; i++)
{
if(s.Inters(sg[i]))
continue; Segment t1(sg[i-].S, sg[i].S);
Segment t2(sg[i-].E, sg[i].E); if(s.Inters(t1))
{
Point tmp = s.crossNode(t1);
ans = tmp.x;
}
if(s.Inters(t2))
{
Point tmp = s.crossNode(t2); if(fabs(ans-oo) < EPS)
ans = tmp.x;
else
ans = max(ans, tmp.x);
} break;
} return ans;
} int main()
{
int N; while(scanf("%d", &N) != EOF && N)
{
Point p[MAXN];
Segment sg[MAXN]; int k=; for(int i=; i<N; i++, k+=)
{
scanf("%lf%lf", &p[k].x, &p[k].y);
p[k+].x = p[k].x, p[k+].y = p[k].y - 1.0;
sg[i] = Segment(p[k], p[k+]);
} double ans = -oo; for(int i=; i<k; i++)
for(int j=i+; j<k; j++)
{
if(fabs(p[i].x-p[j].x) < EPS)
continue; Segment s(p[i], p[j]);
s.MakeNewSeg(sg[].S.x, sg[N-].S.x); if(s.Inters(sg[]))
ans = max(ans, FindMinX(s, sg, N));
/// printf("i=%d, j=%d, ans=%f\n", i, j, ans);
} if(fabs(ans-oo) < EPS)
printf("Through all the pipe.\n");
else
printf("%.2f\n", ans);
} return ;
}

Pipe - POJ 1039(线段相交交点)的更多相关文章

  1. poj 1066 线段相交

    链接:http://poj.org/problem?id=1066 Treasure Hunt Time Limit: 1000MS   Memory Limit: 10000K Total Subm ...

  2. poj 1269 线段相交/平行

    模板题 注意原题中说的线段其实要当成没有端点的直线.被坑了= = #include <cmath> #include <cstdio> #include <iostrea ...

  3. poj 2653 线段相交

    题意:一堆线段依次放在桌子上,上面的线段会压住下面的线段,求找出没被压住的线段. sol:从下向上找,如果发现上面的线段与下面的相交,说明被压住了.break掉 其实这是个n^2的算法,但是题目已经说 ...

  4. poj 2653 线段相交裸题(解题报告)

    #include<stdio.h> #include<math.h> const double eps=1e-8; int n; int cmp(double x) { if( ...

  5. poj 1410 线段相交判断

    http://poj.org/problem?id=1410 Intersection Time Limit: 1000MS   Memory Limit: 10000K Total Submissi ...

  6. HDU 2150 Pipe( 判断线段相交水 )

    链接:传送门 题意:略 思路:数据量很小,直接暴力所有线段 /********************************************************************* ...

  7. Pick-up sticks - POJ 2653 (线段相交)

    题目大意:有一个木棒,按照顺序摆放,求出去上面没有被别的木棍压着的木棍.....   分析:可以维护一个队列,如果木棍没有被压着就入队列,如果判断被压着,就让那个压着的出队列,最后把这个木棍放进队列, ...

  8. The Doors - POJ 1556 (线段相交)

    题目大意:有一个房间(左上角(0,10),右下角(10,0)),然后房间里有N面墙,每面墙上都有两个门,求出来从初始点(0,5),到达终点(10,5)的最短距离.   分析:很明显根据两点之间直线最短 ...

  9. POJ1269 Intersecting Lines[线段相交 交点]

    Intersecting Lines Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 15145   Accepted: 66 ...

随机推荐

  1. Github上图文演示仓库创建

    1.注册账号 https://github.com/ 2.注册完账号 创建仓库 a.点击按钮 Start a project b.填写信息,点击按钮 Create repository c.仓库信息( ...

  2. java_泛型(2016-11-17)

    没有自己敲,这篇博客讲的不错,直接记录. 犯懒啊 重点关注 T,?以及擦除 Java总结篇系列:Java泛型:http://www.cnblogs.com/lwbqqyumidi/p/3837629. ...

  3. PC110305/UVA10188

    根据我的规律,每天solved3题就感觉不行了~但是今天好像做水题做上瘾了,不过PC的题目尽管水,水得还是可以让人有进步. 这题OJ自动测评真心坑,题目看起来十分简单,测评返回三种可能: Accept ...

  4. 深入了解jquery中的键盘事件

    很多时候,我们需要获取用户的键盘事件,下面就一起来看看jquery是如何操作键盘事件的. 一.首先需要知道的是: 1.keydown() keydown事件会在键盘按下时触发. 2.keyup() k ...

  5. Struts2常规配置

    默认配置文件名:struts.xml   WEB-INF/classes下(放到src下) Struts2的有效常量可以查看    org\apache\struts2 下的    default.p ...

  6. linux shell获取时间

    获得当天的日期 date +%Y-%m-%d 输出: 2011-07-28 将当前日期赋值给DATE变量DATE=$(date +%Y%m%d) 有时候我们需要使用今天之前或者往后的日期,这时可以使用 ...

  7. Flex时间操作

    小弟是Flex新手,最近一段时间领导要求使用Flex开发B/S的一些项目,需要用到时间上的一些操作.上网查询一番好多人都说不好操作,有的甚至非常麻烦.基于此,小弟整理了一些关于Flex时间操作的经验, ...

  8. ping命令找不到

    重装系统后安装JDK了,网络一直不好,我ping了下,结果显示ping不是内部或者外部命令,在谷歌里百度了下,在环境变量的path后加上“;C:\Windows\System32”即可,果然有效哦. ...

  9. C/C++中的内存对齐 C/C++中的内存对齐

    一.什么是内存对齐.为什么需要内存对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址 ...

  10. Angular1.0

    公司会议室组织分享,两个小时困死我了,一点凌乱笔记: $http.get和promise一样有then方法,成功,失败 jquery each遍历对象i,n ng-app ng-controller ...