1016 - 計算幾何之直線與線段的交 - Segments(POJ 3304)
阿新 • • 發佈:2018-11-10
題意
雖然題目是給了什麼投影啊,什麼奇奇怪怪的東西
但實際上也就是給你 n 條線段,詢問是否存在一條直線能經過所有的線段
資料範圍:n<=100
分析
這個資料範圍有點友好啊……
我們先來想一個問題
若存在一條直線使其能穿過所有的線段,那我們一定可以將這條線段進行一定角度的旋轉,然後使其恰好被卡在某兩條線段的端點之間
也就是說若我們能夠找到被某兩個線段端點卡住的直線,使其穿過所有的線段,則一定存在一組合法解
根據逆反定理,若我們找不到這樣的直線,則原題一定不存在合法解
由於資料範圍很友好,我們就直接暴力列舉(n^3)
程式碼
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #define eps 1e-8 #define N 105 using namespace std; int T,n; struct Point{ double x,y; Point(){} Point(double _x,double _y):x(_x),y(_y){} friend inline Point operator +(const Point &a,const Point &b){ return Point(a.x+b.x,a.y+b.y); } friend inline Point operator -(const Point &a,const Point &b){ return Point(a.x-b.x,a.y-b.y); } friend inline Point operator *(double k,const Point &a){ return Point(k*a.x,k*a.y); } friend inline double dot(const Point &a,const Point &b){ return (a.x*b.x+a.y*b.y); } friend inline double cross(const Point &a,const Point &b){ return (a.x*b.y-b.x*a.y); } friend inline double len(const Point &a){ return sqrt(dot(a,a)); } friend inline double dis (const Point &a,const Point &b){ return len(a-b); }//向量常見的運算 }; struct Line{ Point a,b; }line[N]; bool check(Point x,Point y){ if(dis(x,y)<eps) return false;//必須要要的 for(int i=1;i<=n;++i){ if(cross(x-line[i].a,y-line[i].a)*cross(x-line[i].b,y-line[i].b)>eps) return false; } return true; } int main(){ scanf("%d",&T); int i,j,k; while(T--){ scanf("%d",&n); for(i=1;i<=n;++i) scanf("%lf%lf%lf%lf",&line[i].a.x,&line[i].a.y,&line[i].b.x,&line[i].b.y); if(n==1){ printf("Yes!\n");continue; } int flag=0; for(i=1;i<n;++i) { for(j=i+1;j<=n;++j){ if(check(line[i].a,line[j].a)||check(line[i].a,line[j].b)||check(line[i].b,line[j].a)||check(line[i].b,line[j].b)){ flag=1; break; } } if(flag){ printf("Yes!\n"); break; } } if(!flag) printf("No!\n"); } return 0; }