HDU-1086 You can Solve a Geometry Problem too 解题报告
2012-02-16 11:17
190 查看
[b][b][b]Description[/b][/b][/b]
Many geometry(几何)problems were designed in the ACM/ICPC. Andnow, I also prepare a geometry problem for this final exam. According to theexperience of many ACMers, geometry problems are always
much trouble, but thisproblem is very easy, after all we are now attending an exam, not a contest :)
Give you N (1<=N<=100) segments(线段), please output the number of allintersections(交点). You should countrepeatedly if M (M>2) segments intersect at the same point.
Note:
You can assume that two segments would not intersect at more than one point.
[b][b][b]Input[/b][/b][/b]
Input containsmultiple test cases. Each test case contains a integer N (1=N<=100) in aline first, and then N lines follow. Each line describes one segment with fourfloat values x1, y1, x2, y2
which are coordinates of the segment’s ending.
A test case starting with 0 terminates the input and this test case is not tobe processed.
[b][b][b][/b][/b][/b]
Output
For each case,print the number of intersections, and one line one case.
[b][b][b]Sample Input[/b][/b][/b]
2
0.00 0.00 1.001.00
0.00 1.00 1.000.00
3
0.00 0.00 1.001.00
0.00 1.00 1.000.000
0.00 0.00 1.000.00
0
Sample Output
1
3
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1086
解法类型:向量叉乘
解题思路:一道计算几何入门题,首先要有判断两条线段是否相交的预备知识,当然后很多方法。如把线段化为直线看交点所在的区间,或者建立向量,看线段一端点与另一线段的两端点的两个向量的夹角是否小于180°等等。这里用到一种朴实的方法,即向量叉乘判断法:
判断两线段是否相交:
我们分两步确定两条线段是否相交:
(1)快速排斥试验
设以线段 P1P2
为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,如果R和T不相交,显然两线段不会相交。
(2)跨立试验
如果两线段相交,则两线段必然相互跨立对方。若P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0。上式可改写成( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0。当 ( P1 - Q1 ) × ( Q2 -
Q1 ) = 0 时,说明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共线,但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。所以判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。同理判断Q1Q2跨立P1P2的依据是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 -
P1 ) × ( Q2 - P1 ) >= 0。具体情况如下图所示:
![](http://dev.gameres.com/Program/Abstract/Geometry_2.gif)
算法实现:
Many geometry(几何)problems were designed in the ACM/ICPC. Andnow, I also prepare a geometry problem for this final exam. According to theexperience of many ACMers, geometry problems are always
much trouble, but thisproblem is very easy, after all we are now attending an exam, not a contest :)
Give you N (1<=N<=100) segments(线段), please output the number of allintersections(交点). You should countrepeatedly if M (M>2) segments intersect at the same point.
Note:
You can assume that two segments would not intersect at more than one point.
[b][b][b]Input[/b][/b][/b]
Input containsmultiple test cases. Each test case contains a integer N (1=N<=100) in aline first, and then N lines follow. Each line describes one segment with fourfloat values x1, y1, x2, y2
which are coordinates of the segment’s ending.
A test case starting with 0 terminates the input and this test case is not tobe processed.
[b][b][b][/b][/b][/b]
Output
For each case,print the number of intersections, and one line one case.
[b][b][b]Sample Input[/b][/b][/b]
2
0.00 0.00 1.001.00
0.00 1.00 1.000.00
3
0.00 0.00 1.001.00
0.00 1.00 1.000.000
0.00 0.00 1.000.00
0
Sample Output
1
3
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1086
解法类型:向量叉乘
解题思路:一道计算几何入门题,首先要有判断两条线段是否相交的预备知识,当然后很多方法。如把线段化为直线看交点所在的区间,或者建立向量,看线段一端点与另一线段的两端点的两个向量的夹角是否小于180°等等。这里用到一种朴实的方法,即向量叉乘判断法:
判断两线段是否相交:
我们分两步确定两条线段是否相交:
(1)快速排斥试验
设以线段 P1P2
为对角线的矩形为R, 设以线段 Q1Q2 为对角线的矩形为T,如果R和T不相交,显然两线段不会相交。
(2)跨立试验
如果两线段相交,则两线段必然相互跨立对方。若P1P2跨立Q1Q2 ,则矢量 ( P1 - Q1 ) 和( P2 - Q1 )位于矢量( Q2 - Q1 ) 的两侧,即( P1 - Q1 ) × ( Q2 - Q1 ) * ( P2 - Q1 ) × ( Q2 - Q1 ) < 0。上式可改写成( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) > 0。当 ( P1 - Q1 ) × ( Q2 -
Q1 ) = 0 时,说明 ( P1 - Q1 ) 和 ( Q2 - Q1 )共线,但是因为已经通过快速排斥试验,所以 P1 一定在线段 Q1Q2上;同理,( Q2 - Q1 ) ×(P2 - Q1 ) = 0 说明 P2 一定在线段 Q1Q2上。所以判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) × ( Q2 - Q1 ) * ( Q2 - Q1 ) × ( P2 - Q1 ) >= 0。同理判断Q1Q2跨立P1P2的依据是:( Q1 - P1 ) × ( P2 - P1 ) * ( P2 -
P1 ) × ( Q2 - P1 ) >= 0。具体情况如下图所示:
![](http://dev.gameres.com/Program/Abstract/Geometry_2.gif)
算法实现:
//STATUS:C++_AC_15MS_204K #include<stdio.h> int is_inter(struct Segment a,struct Segment b); //跨立实验 int is_fxiji(struct Segment a,struct Segment b); //快速排斥 const int MAXN=100; struct Segment{ double x1,y1,x2,y2; }seg[MAXN]; int main() { int i,j,n,m; while(scanf("%d",&n)&&n) { for(i=0;i<n;i++) scanf("%lf%lf%lf%lf",&seg[i].x1,&seg[i].y1,&seg[i].x2,&seg[i].y2); for(i=0,m=0;i<n-1;i++) for(j=i+1;j<n;j++){ if(is_fxiji(seg[i],seg[j])) if(is_inter(seg[i],seg[j])&&is_inter(seg[j],seg[i])) //要分别对两直线进行跨立实验,才是两直线相交的充分必要条件 m++; } printf("%d\n",m); } return 0; } int is_inter(Segment a,Segment b) //跨立实验 { double x[3],y[3]; x[0]=a.x1-b.x2,y[0]=a.y1-b.y2, x[1]=b.x2-b.x1,y[1]=b.y2-b.y1, x[2]=a.x2-b.x1,y[2]=a.y2-b.y1; if((x[0]*y[1]-x[1]*y[0])*(x[2]*y[1]-x[1]*y[2])>0)return 0; return 1; } int is_fxiji(struct Segment a,struct Segment b) //快速排斥,RT是否相交 { double t; if(a.x1>a.x2)t=a.x1,a.x1=a.x2,a.x2=t; if(b.x1>b.x2)t=b.x1,b.x1=b.x2,b.x2=t; if(b.x1>a.x2||b.x2<a.x1)return 0; if(a.y1>a.y2)t=a.y1,a.y1=a.y2,a.y2=t; if(b.y1>b.y2)t=b.y1,b.y1=b.y2,b.y2=t; if(b.y1>a.y2||b.y2<a.y1)return 0; return 1; }
相关文章推荐
- HDU-1086 You can Solve a Geometry Problem too 解题报告
- hdu 1086 You can Solve a Geometry Problem too(计算几何水题)
- Hdu 1086 You can Solve a Geometry Problem too[判断线段相交,完整版]
- HDU 1086 You can Solve a Geometry Problem too
- 向量判断HDU 1086 线段交点 You can Solve a Geometry Problem too
- HDU 1086 You can Solve a Geometry Problem too(判断两条直线是否相交)
- HDU-1086-You can Solve a Geometry Problem too
- HDU 1086 You can Solve a Geometry Problem too
- HDU 1086 You can Solve a Geometry Problem too(判断两线段是否相交)跨立实验
- HDU 1086 You can Solve a Geometry Problem too
- hdu_1086 You can Solve a Geometry Problem too(计算几何)
- HDU 1086 You can Solve a Geometry Problem too(判定线段相交 规范相交和非规范相交)
- hdu 1086:You can Solve a Geometry Problem too(计算几何,判断两线段相交,水题)
- HDU 1086 You can Solve a Geometry Problem too
- HDU-1086-You can Solve a Geometry Problem too
- hdu 1086 You can Solve a Geometry Problem too(线段相交+枚举)
- HDU 1086 You can Solve a Geometry Problem too 判断任意两线段是否相交
- hdu 1086 You can Solve a Geometry Problem too(求线段相交点个数 模板)
- HDU 1086 You can Solve a Geometry Problem too (判断线段相交)
- HDU 1086 You can Solve a Geometry Problem too(简单的线段相交)