POJ 1127 跨立實驗和快速排斥實驗
阿新 • • 發佈:2018-11-11
還是那道題 但是這次有一個全新的解法了,涉及到的跨立實驗和快速排斥實驗,在學習部分我有提及過。
不多說直接上一下核心程式碼
直接進行雙實驗,如果快速排斥不通過 直接PASS 之後再進行跨立實驗,如果成了 那麼兩直線相交
bool judge(point p1,point p2,point q1,point q2) { if( max(p1.x,p2.x)<min(q1.x,q2.x)|| //快速排斥實驗 max(q1.x,q2.x)<min(p1.x,p2.x)|| max(p1.y,p2.y)<min(q1.y,q2.y)|| max(q1.y,q2.y)<min(p1.y,p2.y)) return 0; if((q1-p1).det(q2-p1) * (q1-p2).det(q2-p2) <=0 && (p1-q1).det(p2-q1) * (p1-q2).det(p2-q2)<=0) //跨立實驗 return 1; else return 0; }
之後。。雖然和本題無太大關係。。但是我又學會一種新的並查集路徑壓縮。。網上的大牛真實厲害
int findd(int v)
{
if(pre[v]==v)
return v;
else
{
pre[v]=findd(pre[v]);//路徑壓縮
return pre[v];
}
}
以下是完整程式碼。。不得不說,用了這兩個實驗進行相交判定,整串程式碼都顯得清爽了不少
(原來的函式並沒有刪除)
#include<iostream> #include<cmath> #include<cstdio> using namespace std; const double eps = 1e-10; int pre[30]; double add(double a,double b) { if(abs(a+b)<eps*(abs(a)+abs(b))) return 0; else return a+b; } struct point { double x,y; point(){} point(double x,double y): x(x),y(y){} point operator- (point p) { return point(add(x, -p.x),add(y, -p.y)); } point operator+ (point p) { return point(add(x, p.x),add(y, p.y)); } point operator* (double d) { return point(x*d, y*d); } double dot(point p) { return add(x*p.x,y*p.y); } double det(point p) { return add(x*p.y,-y*p.x); } }; point p[30],q[30]; bool on_seg(point p1, point p2, point q) { return (p1 - q).det(p2 - q) == 0 && (p1 - q).dot(p2 - q) <= 0; } point inter(point p1, point p2, point q1, point q2) { return p1 + (p2 - p1) * ((q2 - q1).det(q1 - p1) / (q2 - q1).det(p2 - p1)); } int findd(int v) { if(pre[v]==v) return v; else { pre[v]=findd(pre[v]);//路徑壓縮 return pre[v]; } } void unite(int x,int y) { int fx=findd(x); int fy=findd(y); if(fx!=fy) pre[fy]=fx; } bool same(int x,int y) { return findd(x)==findd(y); } bool judge(point p1,point p2,point q1,point q2) { if( max(p1.x,p2.x)<min(q1.x,q2.x)|| //快速排斥實驗 max(q1.x,q2.x)<min(p1.x,p2.x)|| max(p1.y,p2.y)<min(q1.y,q2.y)|| max(q1.y,q2.y)<min(p1.y,p2.y)) return 0; if((q1-p1).det(q2-p1) * (q1-p2).det(q2-p2) <=0 && (p1-q1).det(p2-q1) * (p1-q2).det(p2-q2)<=0) //跨立實驗 return 1; else return 0; } int main() { int n; while(~scanf("%d",&n)&&n) { for(int i=0;i<=n;i++) pre[i]=i; for(int i=1;i<=n;i++) { cin>>p[i].x>>p[i].y; cin>>q[i].x>>q[i].y; } for(int i=1;i<=n;i++) { for(int j=1;j<i;j++) { if(judge(p[i],q[i],p[j],q[j])) unite(i,j); } } int x,y; while(~scanf("%d%d",&x,&y)&&x&&y) { if(same(x, y)) printf("CONNECTED\n"); else printf("NOT CONNECTED\n"); } } return 0; }