POJ 1039 Pipe 判断直线与线段相交(规范相交, 非规范相交),没有共线情况
2013-08-29 10:34
399 查看
昨天晚上开始想这题,一拿到题目,数据才30,果断想到枚举,而且有一点可以肯定:光线必然贴着其中的2个顶点,不贴顶点根本无法做;
刚开始想得超复杂,枚举任意2个点组成的直线,然后跟所有边界线判断是否相交等等情况, 由于边想别敲,结果才我写得发现有漏洞,而且很难用语言改正,所以放弃了,不久就郁闷地睡觉去了,想想有没有好的方法。
第二天起来,还是想这个问题,诶,想想有什么新方法。真心想不出来, 结果无聊去看了看汝的黑书,发现这题在黑书P359,我也是把前面的计算几何看完了才看到的。
结果刚学了上一个模板就来做这题,先看了看黑书上的思路,诶,我快速打了一遍,直线和线段相交求交点 被我打成 两线段相交求交点, 囧啊, 然后重新打了1遍,1A,真够郁闷的;
黑书思路 + 我的理解:光线最远时,必然有一条线满足最优解(x的值),且 都至少经过 1个上顶点,1个下顶点。
最优路线 有很多,但题目只让我们求最优解,随便找个最优路线都可以代表最优解。
证明:任何直线只要做一下变换都能得到 满足以上条件的直线。
不碰任何顶点 ----->上下平移 ----->碰到一个顶点 ------>绕此点旋转 ------->碰到两个顶点------->绕前点或后点旋转------->碰到一上一下两个顶点。
View Code
懒得解释代码。
学到了:模板必须灵活使用,不然很悲剧的
刚开始想得超复杂,枚举任意2个点组成的直线,然后跟所有边界线判断是否相交等等情况, 由于边想别敲,结果才我写得发现有漏洞,而且很难用语言改正,所以放弃了,不久就郁闷地睡觉去了,想想有没有好的方法。
第二天起来,还是想这个问题,诶,想想有什么新方法。真心想不出来, 结果无聊去看了看汝的黑书,发现这题在黑书P359,我也是把前面的计算几何看完了才看到的。
结果刚学了上一个模板就来做这题,先看了看黑书上的思路,诶,我快速打了一遍,直线和线段相交求交点 被我打成 两线段相交求交点, 囧啊, 然后重新打了1遍,1A,真够郁闷的;
黑书思路 + 我的理解:光线最远时,必然有一条线满足最优解(x的值),且 都至少经过 1个上顶点,1个下顶点。
最优路线 有很多,但题目只让我们求最优解,随便找个最优路线都可以代表最优解。
证明:任何直线只要做一下变换都能得到 满足以上条件的直线。
不碰任何顶点 ----->上下平移 ----->碰到一个顶点 ------>绕此点旋转 ------->碰到两个顶点------->绕前点或后点旋转------->碰到一上一下两个顶点。
View Code
#include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> using namespace std; #define eps 10e-8 #define inf 1<<29 struct point { double x, y; }; double det(double x1, double y1, double x2, double y2) { return x1 * y2 - x2 * y1; } double cross(point o, point a, point b) { return det(a.x - o.x, a.y - o.y, b.x - o.x, b.y - o.y); } bool seg_cross(point a, point b, point c, point d)//判断直线 和 线段是否相交(规范相交 ,非规范相交,不考虑共线) { return ( cross(a, b, c) * cross(a, b, d) <= 0); } int dblcmp(double d) { if( fabs(d) < eps) return 0; return d > 0 ? 1 : -1; } double intersection(point a, point b, point c, point d)//求直线 和线段的交点, //注意 a,b是直线的端点,c,d是线段的端点,别调用错了 { double s1, s2; int d1, d2; d1 = dblcmp(s1 = cross(a, b, c)); d2 = dblcmp(s2 = cross(a, b, d)); if(d1 ^ d2 == -2) return (c.x * s2 - d.x * s1) / (s2 - s1); if(d1 == 0) return c.x; if(d2 == 0) return d.x; return - inf; } point up[22], down[22]; double tmp, max_x; int main() { int i, j, k, n; while( ~scanf("%d", &n) && n) { for(i = 1; i <= n; i++) { scanf("%lf%lf", &up[i].x, &up[i].y); down[i].y = up[i].y - 1; down[i].x = up[i].x; } max_x = up[1].x; for(i = 1; i <= n; i++) for(j = 1; j <= n; j++) { if(i == j)continue; if( !seg_cross(up[i], down[j], up[1], down[1]) )//判断 枚举的直线与 入射口那垂直于x轴的线 是否相交, 相交说明能入射,否则不能,排除这情况 continue; for(k = 2; k <= n; k++) { if( !seg_cross(up[i], down[j], up[k], down[k])) { if( seg_cross(up[i], down[j], up[k - 1], up[k]) ) { tmp = intersection(up[i], down[j], up[k - 1], up[k]); max_x = max (tmp, max_x); } if( seg_cross(up[i], down[j], down[k - 1], down[k]) ) { tmp = intersection(up[i], down[j], down[k - 1], down[k]); max_x = max (tmp, max_x); } break; } } if(k == n + 1){ max_x = up .x; goto loop; } } loop: if(max_x >= up .x)puts("Through all the pipe."); else printf("%.2f\n", max_x); } return 0; }
懒得解释代码。
学到了:模板必须灵活使用,不然很悲剧的
相关文章推荐
- POJ 1039 Pipe 判断直线与线段相交(规范相交, 非规范相交),没有共线情况
- POJ 1039 Pipe(直线和线段相交判断,求交点)
- POJ 1039 Pipe(直线和线段相交判断,求交点)
- poj 1039 Pipe 直线线段相交判断+枚举
- POJ 1039——计算几何初步(判断线段与直线相交)
- poj_1039 Pipe(直线与线段相交)
- POJ 1039 Pipe(线段直线相交)
- POJ 1039 Pipe(计算几何---直线和线段的相交问题)
- POJ-1039 Pipe 枚举+线段相交判断
- poj 1039 Pipe 直线与线段相交
- 简单几何(直线与线段相交) POJ 1039 Pipe
- POJ 1039 Pipe【经典线段与直线相交】
- POJ 1039 Pipe【经典线段与直线相交】
- POJ 3304 判断线段和直线相交
- POJ 1039 Pipe (枚举,判线段相交)
- poj 2074 Line of Sight(视线问题,求直线与线段的交点及判断相交)
- poj 3304 Segments 线段与直线相交的判断
- POJ 1039 直线和线段相交
- poj 1039 Pipe(直线与线段交+枚举直线)
- poj 1039 Pipe (线段相交判定)