ACM-計算幾何之Segments——poj3304
阿新 • • 發佈:2019-02-08
Segments
Input
Input begins with a number T showing the number of test cases and then, T test cases follow. Each test case begins with a line containing a positive integer n ≤ 100 showing the number of segments. After that, n lines containing four real numbers x1 y1 x2 y2 follow, in which (x1, y1) and (x2, y2) are the coordinates of the two endpoints for one of the segments.
Output
For each test case, your program must output "Yes!", if a line with desired property exists and must output "No!" otherwise. You must assume that two floating point numbers a and b are equal if |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
Sample Output
Yes!
Yes!
Description
Given n segments in the two dimensional space, write a program, which determines if there exists a line such that after projecting these segments on it, all projected segments have at least one point in common.Input
Input begins with a number T showing the number of test cases and then, T test cases follow. Each test case begins with a line containing a positive integer n ≤ 100 showing the number of segments. After that, n lines containing four real numbers x1 y1 x2 y2 follow, in which (x1, y1) and (x2, y2) are the coordinates of the two endpoints for one of the segments.
Output
For each test case, your program must output "Yes!", if a line with desired property exists and must output "No!" otherwise. You must assume that two floating point numbers a and b are equal if |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
Yes!
Yes!
No!
求是否存在一條直線可以與列出的所有線段相交。
解題:如果存在這麼一條直線,必定過平面中的兩個點,
所以任意窮舉兩個點所在的直線與所有線段判斷是否相交。
這道題還有注意精度問題。
#include <iostream> #define MAX 201 using namespace std; int n; // 精度判定 const double eps = 1E-8; int sig(double d) { return (d>eps) - (d<-eps); } struct Point { double x,y; }point[MAX]; double cross(Point &o,Point& a,Point &b) { return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x); } //判斷直線ab是否與線段cd相交 //0 不相交 //1 規範相交 //2 不規範相交 int segLineCross(Point &a,Point &b,Point &c,Point &d) { int d1,d2; d1 = sig(cross(a,b,c)); d2 = sig(cross(a,b,d)); if((d1^d2)==-2)//注意加小括號,^的優先順序比==低 return 1; if(d1==0 || d2==0) return 2; return 0; } bool Test(Point &a,Point &b)//判斷直線ab是否與所有線段相交 { int i; if(sig(a.x-b.x)==0 && sig(a.y-b.y)==0)//★判斷重複點 return false; for(i=0;i<2*n;i+=2) if(segLineCross(a,b,point[i],point[i+1])==0) return false; return true; } bool Find() { int i,j; for(i=0;i<2*n;++i) for(j=0;j<2*n;++j) if(Test(point[i],point[j])) return true; return false; } int main() { int test,i; cin >> test; while(test--) { cin >> n; for(i=0;i<2*n;++i) cin>>point[i].x>>point[i].y; if(Find()) cout << "Yes!" << endl; else cout << "No!" << endl; } return 0; }