POJ 3304 Segments
题目大意:
给出n条线段两个端点的坐标,问所有线段投影到一条直线上,
如果这些所有投影至少相交于一点就输出Yes!,否则输出No!。
输入:
输入以t开头,显示测试用例的数量,然后,t测试用例跟随。每个测试案例以一行包含一个正整数n≤100显示段数。在那之后,N行包含四个实数x1 y1 x2 y2跟随,以(x1,y1),(x2,y2)是一个段的两个端点坐标。
输出:
对于每个测试用例,若存在您的程序必须输出“Yes!”,否则必须输出“No!”否则。你假设A和B两浮点数相等,当且| A-B |<10-8。
Sample Input
3
2
1.0 2.0 3.0 4.0
4.0 5.0 6.0 7.0
3
0.0 0.0 0.0 1.0
0.0 1.0 0.0 2.0
1.0 1.0 2.0 1.0
3
0.0 0.0 0.0 1.0
0.0 2.0 0.0 3.0
1.0 1.0 2.0 1.0
Sample Output
Yes!
Yes!
No!
题解:计算几何
所有线段投影到一条线段都有公共点等价于存在一条垂线,与所有线段相交
判断相交可以用跨立实验,要注意浮点数误差
若存在一条这样的直线,可知存在一条符合条件的直线经过两个端点
还要考虑重点
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 struct Node 8 { 9 double x1,y1,x2,y2; 10 } line[10001]; 11 double eps=1e-8; 12 int n; 13 double cross(double x1,double y1,double x2,double y2,int i) 14 { 15 double dx=x2-x1,dy=y2-y1; 16 double px=line[i].x1-x1,py=line[i].y1-y1; 17 double fx=line[i].x2-x1,fy=line[i].y2-y1; 18 return ((px*dy-py*dx)*(fx*dy-fy*dx)); 19 } 20 bool judge(double x1,double y1,double x2,double y2) 21 { 22 int i; 23 if (sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))<eps) return 0; 24 for (i=1; i<=n; i++) 25 { 26 if (cross(x1,y1,x2,y2,i)>eps) return 0; 27 } 28 return 1; 29 } 30 bool exam(int i,int j) 31 { 32 if (judge(line[i].x1,line[i].y1,line[j].x1,line[j].y1)) return 1; 33 if (judge(line[i].x2,line[i].y2,line[j].x1,line[j].y1)) return 1; 34 if (judge(line[i].x2,line[i].y2,line[j].x2,line[j].y2)) return 1; 35 if (judge(line[i].x1,line[i].y1,line[j].x1,line[j].y1)) return 1; 36 return 0; 37 } 38 int main() 39 { 40 int T,i,ans,j; 41 cin>>T; 42 while (T--) 43 { 44 scanf("%d",&n); 45 for (i=1; i<=n; i++) 46 { 47 scanf("%lf%lf%lf%lf",&line[i].x1,&line[i].y1,&line[i].x2,&line[i].y2); 48 } 49 ans=0; 50 if (n==1) 51 { 52 cout<<"Yes!"<<endl; 53 } 54 else 55 { 56 for (i=1; i<n; i++) 57 { 58 for (j=i+1; j<=n; j++) 59 if (exam(i,j)) 60 { 61 ans=1; 62 break; 63 } 64 if (ans) break; 65 } 66 if (ans) cout<<"Yes!"<<endl; 67 else cout<<"No!"<<endl; 68 } 69 } 70 }