Poj_3304 Segments -线段与直线相交问题(问题转化)
题目:问是否存在一条直线,所有线段在这条直线上投影后至少有一个公共点。
吐槽:先承认,我一开始是按着题目意思去写的,枚举直线,但发现太慢了,最后搜题解才发现这个问题是可以转化的,刚开始打计算几何,涨知识了。
分析:分析方法:从结果去分析(别人博客说的)
1、首先从题目的结果可以看出,最终所有线段的投影至少有一个公共点,那么我们将这公共点连起来不就是一条直线咯,还是一条经过所有线段的直线。
So,问题转化成求是否存在一条直线经过所有线段。
2、然而现在并没有一个可行的方案可以枚举直线,所以我们想想啊,虽然有一条直线经过了所有线段,但是它还可以稍微旋转一些,然后旋啊旋,会发现直线某个位置被某条线段的端点卡住了不能动了,….,最后发现直线完全不能动的时候,直线至少被两个点卡住,而这些点包含了线段的端点。soga,那么就可以枚举线段端点啦。
备注:神器-Cross(叉积)
/************************************************ Author :DarkTong Created Time :2016/8/3 20:36:00 File Name :Poj_3304.cpp *************************************************/ //#include <bits/stdc++.h> #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define eps 1e-8 typedef double Db; struct Point { Db x, y; Point(Db x=0, Db y=0):x(x), y(y){} }C; typedef Point Vector; //向量或点的四则运算 Vector operator + (Vector A, Vector B){ return Vector(A.x+B.x, A.y+B.y);} Vector operator - (Vector A, Vector B){ return Vector(A.x-B.x, A.y-B.y);} Vector operator * (Vector A, Db p){ return Vector(A.x*p, A.y*p);} int dcmp(Db x){ if(fabs(x)<eps) return 0; else return x<0 ? -1 : 1;} Db Dot(Vector A, Vector B){ return A.x*B.x + A.y*B.y;} /*点积: 角度分布:>0(-90, 90), ==0(90或-90), <0((-180,90)或(90,180])*/ Db Cross(Vector A, Vector B){ return A.x*B.y - A.y*B.x;} /*叉积(判<180的角): ==0(共线), >0(逆时针*/ //判断点是否在线段上 /*****************************************************************************/ const int maxn = 100 + 10; int n, np; Point line[maxn][2], poi[maxn*2]; bool solve() { for(int i=0;i<np;++i) { for(int j=i+1;j<np;++j) { Vector v = poi[j]-poi[i]; if(dcmp(v.x)==0&&dcmp(v.y)==0) continue; Point P = poi[i]; int f=1; for(int k=0;k<n;++k) { int k1 = dcmp(Cross(line[k][0]-P, v)); int k2 = dcmp(Cross(v, line[k][1]-P)); if(k1*k2<0) { f=0; break; } } if(f) return true; } } return false; } int main() { int T, cas=1; scanf("%d", &T); while(T--) { scanf("%d", &n); np=0; for(int i=0;i<n;++i) { scanf("%lf%lf%lf%lf", &line[i][0].x, &line[i][0].y, &line[i][1].x, &line[i][1].y); poi[np++]=line[i][0]; poi[np++]=line[i][1]; } if(solve()) puts("Yes!"); else puts("No!"); } return 0; }