poj 1066 Treasure Hunt(線段相交)
阿新 • • 發佈:2018-12-18
題意:
給你一個100*100的正方形,再給你n條線(牆),保證線段一定在正方形內且端點在正方形邊界(外牆),最後給你一個正方形內的點(保證不再牆上)
告訴你牆之間(包括外牆)圍成了一些小房間,在小房間內可以從房間邊界(牆)的中點走過這堵牆,問你從給定的點走到外牆外最少走過的牆數。
題解:直接把中心點與邊界點連成線段,並判斷有多少條線段與之相交,最小的相交數就是答案,詳情見程式碼。
///把中心點與邊界上的點連線,遍歷n條線段,有多少次相交,就要破多少個牆 #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; #define INF 0x3f3f3f3f struct point{ double x,y; point(){} point(double _x,double _y){ x=_x;y=_y; } }; struct Line{ point a,b; Line(){} Line(point _a,point _b){ a=_a;b=_b; } }; point operator + (point a,point b) {return point(a.x+b.x,a.y+b.y);} point operator - (point a,point b) {return point(a.x-b.x,a.y-b.y);} point operator * (point a,double p) { return point(a.x*p,a.y*p);} point operator / (point a,double p){ return point(a.x/p,a.y/p);} bool operator < (const point &a,const point &b){ return a.x<b.x||(a.x==b.x&&a.y<b.y); } const double esp=1e-8; int dcmp(double x){ if(fabs(x)<1e-8) return 0; else return x<0?-1:1; } bool operator ==(const point &a,const point &b){ return dcmp(a.x-b.x)==0&&dcmp(a.y-b.y)==0; } double Cross(point a,point b){ return a.x*b.y-a.y*b.x;} bool isCross(point s1,point e1,point s2,point e2)///判斷線段相交判定 { ///第一步,快速排斥實驗 if(!(min(s1.x,e1.x)<=max(s2.x,e2.x)&&min(s2.x,e2.x)<=max(s1.x,e1.x)&& min(s1.y,e1.y)<=max(s2.y,e2.y)&&min(s2.y,e2.y)<=max(s1.y,e1.y))) return false; ///首先判斷向量s2e2 跨立 向量s1e1 double c1=Cross(s2-s1,e1-s1),c2=Cross(e1-s1,e2-s1); ///再次判斷向量s1e1 跨立 向量 s2e2 double c3=Cross(s1-s2,e2-s2),c4=Cross(e2-s2,e1-s2); ///==0表示,相交於端點也認定為相交 // printf("c1=%f,c2=%f,c3=%f,c4=%f\n",c1,c2,c3,c4); if(dcmp(c1*c2)>0&&dcmp(c3*c4)>0) return true; return false; } Line line[50]; int n; int check(point s1,point e1) { int item=0; for(int i=1;i<=n;i++) { if(isCross(s1,e1,line[i].a,line[i].b)) item++; ///此題相交於端點不算 } return item; } int main() { while(~scanf("%d",&n)) { double x1,y1,x2,y2; for(int i=1;i<=n;i++) { scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); line[i]=Line(point(x1,y1),point(x2,y2)); } point center; scanf("%lf%lf",¢er.x,¢er.y); if(n==0){ printf("Number of doors = 1\n");continue; } int mins=INF; for(int i=1;i<=n;i++) ///遍歷邊界的點 { mins=min(mins,check(line[i].a,center)); mins=min(mins,check(line[i].b,center)); } mins=min(mins,check(point(0,0),center)); ///四個頂角 mins=min(mins,check(point(0,100),center)); mins=min(mins,check(point(100,0),center)); mins=min(mins,check(point(100,100),center)); printf("Number of doors = %d\n",mins+1); } return 0; }