[poj 1039]Pipes[线段相交求交点]
来源:互联网 发布:各国域名后缀大全 编辑:程序博客网 时间:2024/05/18 02:28
题意:
无反射不透明管子, 问从入口射入的所有光线最远能到达的横坐标. 贯穿也可.
思路:
枚举每一组经过 up [ i ] 和 down [ j ] 的直线, 计算最远点.
因为无法按照光线生成的方式确定点斜式的起始点及斜率(连续的), 于是换另一种思路:
反正最终是要判断可行的直线, 就直接选择一些有代表性的直线, 覆盖所有边界即可.
于是考虑边界是什么.
首先可以发现: 由于光线是入口整个发出的, 其实也就是入口和拐点是平等的. 只要判相交.
只要覆盖在整个管道范围内的直线就可以, 由于不知道管道的形状特点, 只能暴力枚举每一组上下界. 能够完全穿过的直线就取"恰好与出口的一端相交"的情况.
这样做就将当前所枚举的两端点视为一段管道, 当前直线可以穿过当前等效管道, 判别是否可以穿过其他管道(包括等效管道内部的真实管道).
也就是将一系列判别满足的问题拆分为, 保证单个问题满足, 并用此一单个问题 粗略划定的范围去测试其它. 这样就解决了用来测试的范围无从确定的障碍.
难点就在于想到如何遍历所有可行的直线.
//Memory Time//456K 63MS#include<iostream>#include<cmath>#include<iomanip>using namespace std;const double precision=1e-3; //精度限制const double inf=99999.0; //正无穷,注意下面使用的是负无穷typedef class Node //折点坐标{public:double x;double y;}point;int max(int a,int b){return a>b?a:b;}/*把浮点p的值转化为0,1或-1 (精度讨论)*/int dblcmp(double p){if(fabs(p)<precision) // fabs() 浮点数的绝对值return 0; //只要是在0的邻域,就认为是0return p>0?1:-1;}/*叉积运算*/double det(double x1,double y1,double x2,double y2){return x1*y2-x2*y1;}/*计算P点在AB的顺侧还是逆侧*/double cross(point A,point B,point P)//AB x AP{return det(B.x-A.x , B.y-A.y , P.x-A.x , P.y-A.y);}/*判断直线AB与线段CD是否相交*/bool check(point A,point B,point C,point D){return (dblcmp(cross(A,B,C)) * dblcmp(cross(A,B,D)) <= 0);//在异侧或在线上}/*计算直线AB和线段CD的交点横坐标*/double intersection(point A,point B,point C,point D){double area1=cross(A,B,C);double area2=cross(A,B,D);int c=dblcmp(area1);int d=dblcmp(area2);if(c*d<0) //C,D在直线AB的两侧,规范相交return (area2*C.x - area1*D.x)/(area2-area1); //交点计算公式if(c*d==0){ //CD的其中一个端点在AB上,不规范相交if(c==0)return C.x;elsereturn D.x;}return -inf; //CD在AB同侧,无交点,返回 负无穷}int main(){int n,i,j,k; //折点数while(cin>>n){if(!n)break;point* up=new point[n+1]; //上折点point* down=new point[n+1]; //下折点double max_x=-inf; //最大可见度(管中最远可见点的横坐标)/*Input*/for(i=1;i<=n;i++){cin>>up[i].x>>up[i].y;down[i].x=up[i].x;down[i].y=up[i].y-1;}bool flag=false; //标记当前光线L(直线up[i]->down[j])能否贯通全管for(i=1;i<=n;i++) //枚举所有通过一个上折点、一个下折点的直线{for(j=n;j>=1;j--)if(i!=j){for(k=1;k<=n;k++) //直线L最大延伸到第k-1节管子if(!check(up[i],down[j],up[k],down[k])) //up[k]->down[k]为折点处垂直x轴的直线break;if(k>n)//顺利结束循环,可以贯穿{flag=true;break;}else if(k>max(i,j)) //判断与第k-1节管子的上管壁还是下管壁相交{double temp=intersection(up[i],down[j],up[k],up[k-1]);if(max_x < temp)max_x=temp;temp=intersection(up[i],down[j],down[k],down[k-1]);if(max_x < temp)max_x=temp;}}if(flag)break;}if(flag)cout<<"Through all the pipe."<<endl;elsecout<<fixed<<setprecision(2)<<max_x<<endl;/*Relax Room*/delete up;delete down;}return 0;}自己敲一遍:
#include <cstdio>#include <cmath>using namespace std;const double EPS = 1e-6;///写成int了= =const int INF = 0x3f3f3f3f;const int MAXN = 25;typedef struct node{ double x,y;}point;point up[MAXN],down[MAXN];int max(int a, int b){ int diff = b - a; return b - (diff & (diff>>31));}int dcmp(double p){ if(fabs(p)<EPS) return 0; return p>0?1:-1;}double det(double x1, double y1, double x2, double y2){ return x1*y2 - x2*y1;}double cross(point A, point B, point P){ return det(B.x - A.x, B.y - A.y, P.x - A.x, P.y - A.y);;}bool check(point A, point B, point C, point D){ return (dcmp(cross(A, B, C)) * dcmp(cross(A, B, D)) <= 0);//规范或不规范相交}double intersection(point A, point B, point C, point D){ double area1 = cross(A, B, C); double area2 = cross(A, B, D); int c = dcmp(area1); int d = dcmp(area2); if(c*d<0) { return (area2 * C.x - area1 * D.x)/(area2 - area1); } if(!(c*d)) { if(!c) return C.x; else return D.x; } return -INF;}int main(){ int n; while(scanf("%d",&n)==1 && n) { double Mx = -INF; for(int i=1;i<=n;i++) { scanf("%lf %lf",&up[i].x,&up[i].y); down[i].x = up[i].x,down[i].y = up[i].y - 1; } bool flag = false; for(int i=1;i<=n;i++) { for(int j=1,k;j<=n;j++) { if(i==j) continue; for(k=1;k<=n;k++) { if(!check(up[i],down[j],up[k],down[k])) break; } if(k>n) { flag = true; break; } if(k>max(i,j)) { double temp = intersection(up[i],down[j],up[k],up[k-1]); if(Mx < temp) Mx = temp; temp = intersection(up[i],down[j],down[k],down[k-1]); if(Mx < temp) Mx = temp; } } if(flag) break; } if(flag) printf("Through all the pipe.\n"); else printf("%.2lf\n",Mx); }}
- [poj 1039]Pipes[线段相交求交点]
- POJ 1039-Pipe(计算几何-线段相交、求交点)
- 求线段相交交点坐标
- poj 1269 Intersecting Lines(判断线段相交,并求交点)
- poj 1296 Noise Effect(判断线段相交,并求交点)
- 求射线与线段相交的最多交点 poj 4048
- POJ 1039 Pipe(直线和线段相交判断,求交点)
- POJ1039Pipe【线段相交判断+求交点】
- 判断两线段是否相交求交点
- 判断线段相交并求交点
- 判断两线段相交,并求交点
- POJ 1066 Treasure Hunt 判断线段相交(求交点个数)
- poj 3067 树状数组求逆序数(n条线段相交的交点个数)
- uva 303 pipe (求线段交点,判断线段相交)
- poj 1269 知识点:直线相交判断,求相交交点
- 计算几何 点线的综合题, 精度+ 线段相交+ 求交点 + 求面积 poj 2826 An Easy Problem?! (推荐)
- ArcEngine空间分析之线段相交分析求交点
- 判断两条线段/直线相交,并求交点
- db(分贝)的含义
- PHP引用符&的用法详细解析
- php如何配置和测试GD库
- webkit 硬件渲染相关资料收集
- POJ 一 1002 487-3279
- [poj 1039]Pipes[线段相交求交点]
- tomcat6配置jndi连接数据库的方式
- 你应该更新的JAVA知识
- declare-styleable的使用
- 从多选(multiple)的select中得到所选结果
- iOS开发之摇一摇
- 【主板与硬盘不兼容怎么办?】_8.26
- hdu(2614) Beat
- linux板级内存管理之-物理内存描述的两种实现方法