poj 3304
题意:给出n条线段,判断是否存在一条直线使所有线段在这条直线上的投影有公共部分
首先,如果存在这样的一条直线,那么这条直线的一条垂线一定穿过每一条线段,反之亦然,因此问题就转化成了是否存在一条直线能穿过所有线段
n条线段共2n个点,我们枚举任意两个点构造一条直线与所有线段判断交点即可
注意n=1与n=2时一定合法,同时如果两个点重合就不要枚举
贴代码:
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <stack> using namespace std; double eps=1e-8; struct Point { double x,y; }p[205]; struct Seg { Point st,ed; }s[105]; struct Vec { double x,y; }; double cross_mul(Vec a,Vec b) { return a.x*b.y-a.y*b.x; } int sgn(double x) { if(fabs(x)<eps)return 0; else if(x>0)return 1; return -1; } double get_dis(Point a,Point b) { return sqrt((b.x-a.x)*(b.x-a.x)+(b.y-a.y)*(b.y-a.y)); } int T,n; int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lf%lf%lf%lf",&s[i].st.x,&s[i].st.y,&s[i].ed.x,&s[i].ed.y),p[2*i-1]=s[i].st,p[2*i]=s[i].ed; if(n==1||n==2){printf("Yes!\n");continue;} bool flag=0; for(int i=1;i<=2*n;i++) { for(int j=i+1;j<=2*n;j++) { if(!sgn(get_dis(p[i],p[j])))continue; Vec t0=(Vec){p[j].x-p[i].x,p[j].y-p[i].y}; bool fl=0; for(int k=1;k<=n;k++) { Vec t1=(Vec){s[k].st.x-p[i].x,s[k].st.y-p[i].y}; Vec t2=(Vec){s[k].ed.x-p[i].x,s[k].ed.y-p[i].y}; if(sgn(cross_mul(t0,t1))*sgn(cross_mul(t0,t2))>0){fl=1;break;} } if(!fl){flag=1;break;} } if(flag)break; } if(flag)printf("Yes!\n"); else printf("No!\n"); } return 0; }