判斷平面上是否有一點與所有點相交
阿新 • • 發佈:2020-10-16
poj 3304
#include<iostream> #include<algorithm> #include<cmath> #include<cstdio> using namespace std; #define ll long long const int N = 200+10; const int maxp = 1010; const double eps = 1e-8;//精度 const double inf = 1e20; const double pi = acos(-1.0); int sgn(double x) { if(fabs(x) < eps) return 0; if(x < 0) return -1; else return 1; } struct Point{ double x,y; Point(){} Point(double _x,double _y) { x = _x; y = _y; } void input() { scanf("%lf%lf",&x,&y); } void output() { printf("%.2f,%.2f\n",x,y); } bool operator == (Point b)const{ return sgn(x-b.x) == 0 && sgn(y-b.y) == 0; } bool operator < (Point b)const{ return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x; } Point operator -(const Point &b)const{ return Point(x-b.x,y-b.y); } //叉積 double operator ^(const Point &b)const{ return x*b.y - y*b.x; } //點積 double operator *(const Point &b)const{ return x*b.x + y*b.y; } //返回長度 double len(){ return hypot(x,y);//庫函式 } //返回長度的平方 double len2(){ return x*x + y*y; } //返回兩點的距離 double distance(Point p){ return hypot(x-p.x,y-p.y); } Point operator +(const Point &b)const{ return Point(x+b.x,y+b.y); } Point operator *(const double &k)const{ return Point(x*k,y*k); } Point operator /(const double &k)const{ return Point(x/k,y/k); } //`計算pa 和 pb 的夾角` //`就是求這個點看a,b 所成的夾角` //`測試 LightOJ1203` double rad(Point a,Point b){ Point p = *this; return fabs(atan2( fabs((a-p)^(b-p)),(a-p)*(b-p) )); } //`化為長度為r的向量` Point trunc(double r){ double l = len(); if(!sgn(l))return *this; r /= l; return Point(x*r,y*r); } //`逆時針旋轉90度` Point rotleft(){ return Point(-y,x); } //`順時針旋轉90度` Point rotright(){ return Point(y,-x); } //`繞著p點逆時針旋轉angle` Point rotate(Point p,double angle){ Point v = (*this) - p; double c = cos(angle), s = sin(angle); return Point(p.x + v.x*c - v.y*s,p.y + v.x*s + v.y*c); } }; struct Line{ Point s,e; Line(){} Line(Point _s,Point _e){ s = _s; e = _e; } bool operator ==(Line v){ return (s == v.s)&&(e == v.e); } //`根據一個點和傾斜角angle確定直線,0<=angle<pi` Line(Point p,double angle){ s = p; if(sgn(angle-pi/2) == 0){ e = (s + Point(0,1)); } else{ e = (s + Point(1,tan(angle))); } } //ax+by+c=0 Line(double a,double b,double c){ if(sgn(a) == 0){ s = Point(0,-c/b); e = Point(1,-c/b); } else if(sgn(b) == 0){ s = Point(-c/a,0); e = Point(-c/a,1); } else{ s = Point(0,-c/b); e = Point(1,(-c-a)/b); } } void input(){ s.input(); e.input(); } void adjust(){ if(e < s)swap(s,e); } //求線段長度 double length(){ return s.distance(e); } //`返回直線傾斜角 0<=angle<pi` double angle(){ double k = atan2(e.y-s.y,e.x-s.x); if(sgn(k) < 0)k += pi; if(sgn(k-pi) == 0)k -= pi; return k; } //`點和直線關係` //`1 在左側` //`2 在右側` //`3 在直線上` int relation(Point p){ int c = sgn((p-s)^(e-s)); if(c < 0)return 1; else if(c > 0)return 2; else return 3; } // 點線上段上的判斷 bool pointonseg(Point p){ return sgn((p-s)^(e-s)) == 0 && sgn((p-s)*(p-e)) <= 0; } //`兩向量平行(對應直線平行或重合)` bool parallel(Line v){ return sgn((e-s)^(v.e-v.s)) == 0; } //`兩線段相交判斷` //`2 規範相交` //`1 非規範相交` //`0 不相交` int segcrossseg(Line v){ int d1 = sgn((e-s)^(v.s-s)); int d2 = sgn((e-s)^(v.e-s)); int d3 = sgn((v.e-v.s)^(s-v.s)); int d4 = sgn((v.e-v.s)^(e-v.s)); if( (d1^d2)==-2 && (d3^d4)==-2 )return 2; return (d1==0 && sgn((v.s-s)*(v.s-e))<=0) || (d2==0 && sgn((v.e-s)*(v.e-e))<=0) || (d3==0 && sgn((s-v.s)*(s-v.e))<=0) || (d4==0 && sgn((e-v.s)*(e-v.e))<=0); } //`直線和線段相交判斷` //`-*this line -v seg` //`2 規範相交` //`1 非規範相交` //`0 不相交` int linecrossseg(Line v){ int d1 = sgn((e-s)^(v.s-s)); int d2 = sgn((e-s)^(v.e-s)); if((d1^d2)==-2) return 2; return (d1==0||d2==0); } //`兩直線關係` //`0 平行` //`1 重合` //`2 相交` int linecrossline(Line v){ if((*this).parallel(v)) return v.relation(s)==3; return 2; } //`求兩直線的交點` //`要保證兩直線不平行或重合` Point crosspoint(Line v){ double a1 = (v.e-v.s)^(s-v.s); double a2 = (v.e-v.s)^(e-v.s); return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1)); } //點到直線的距離 double dispointtoline(Point p){ return fabs((p-s)^(e-s))/length(); } //點到線段的距離 double dispointtoseg(Point p){ if(sgn((p-s)*(e-s))<0 || sgn((p-e)*(s-e))<0) return min(p.distance(s),p.distance(e)); return dispointtoline(p); } //`返回線段到線段的距離` //`前提是兩線段不相交,相交距離就是0了` double dissegtoseg(Line v){ return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e))); } //`返回點p在直線上的投影` Point lineprog(Point p){ return s + ( ((e-s)*((e-s)*(p-s)))/((e-s).len2()) ); } //`返回點p關於直線的對稱點` Point symmetrypoint(Point p){ Point q = lineprog(p); return Point(2*q.x-p.x,2*q.y-p.y); } }; Line line[1005]; int n; int check(Point s,Point e) { Line l1 = Line(s,e); if(sgn(l1.length()) == 0) return 0; for(int i=1;i<=n;i++) { if(l1.linecrossseg(line[i]) == 0) { return 0; } } return 1; } void solve() { cin >> n; for(int i=1;i<=n;i++) { line[i].input(); } int flag = 0; for(int i=1;i<=n;i++) { if(flag == 1) break; for(int j=1;j<=n;j++) { if(check(line[i].s,line[j].s) || check(line[i].s,line[j].e) || check(line[i].e,line[j].s) || check(line[i].e,line[j].e)) { flag = 1; break; } } } if(flag) { puts("Yes!"); } else { puts("No!"); } } int main() { int T; scanf("%d",&T); while(T--) { solve(); } return 0; }