题意:给出n条线段,判断是否存在一条直线,使所有线段在该直线上的投影有公共点,是则输出“Yes!”,否则输出“No!”
1<=n<=100,多组测试数据
题解:题目可转化为是否存在一条直线与所有线段都相交(这条直线与题目中所要求的直线垂直)。假如存在这样一条直线,我们显然可以通过移动这条直线使得它与某两条线段的某两个端点相交,则直接枚举线段端点,判断是否符合条件即可,复杂度O(n3)
特判:距离小于1e-8的点视为重合、n=1时一定成功
写的时候犯了不少错误,最后的代码乱糟糟的
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define rep(i,a,b) for(int i=a;i<=b;++i) const double eps=1e-8; struct point{ double x,y; point(){} point (double a,double b): x(a),y(b) {} friend point operator + (const point &a,const point &b){ return point(a.x+b.x,a.y+b.y); } friend point operator - (const point &a,const point &b){ return point(a.x-b.x,a.y-b.y); } friend bool operator == (const point &a,const point &b){ return (abs(a.x-b.x)<eps && abs(a.y-b.y)<eps); } }; inline double det(point a,point b) {return a.x*b.y-a.y*b.x;} inline bool line_cross_segment(point s,point t,point a,point b) { return !(det(s-a,t-a)*det(s-b,t-b)>eps); } point s[200][2]; double sx,sy,tx,ty; int t,n; bool test(int x,int y) { point ts,tt; bool flag=false; rep(i,0,1) { rep(j,0,1) if (!(s[x][i]==s[y][j])) { flag=true; ts=s[x][i];tt=s[y][j]; rep(k,1,n) if (!line_cross_segment(ts,tt,s[k][0],s[k][1])) { flag=false; break; } if (flag) break; } if (flag) break; } if (flag) return true; else return false; } int main() { scanf("%d",&t); bool flag; while (t--) { scanf("%d",&n); flag=false; rep(i,1,n) { scanf("%lf%lf%lf%lf",&sx,&sy,&tx,&ty); s[i][0]=point(sx,sy);s[i][1]=point(tx,ty); } if (n<=2) {printf("Yes! ");continue;} rep(i,1,n) { rep(j,i+1,n) if(test(i,j)) {flag=true;break;} if (flag) break; } if (flag) printf("Yes! ");else printf("No! "); } return 0; }