想看更多的解题报告:http://blog.csdn.net/wangjian8006/article/details/7870410
转载请注明出处:http://blog.csdn.net/wangjian8006
题目大意:给出n条线段两个端点的坐标,问所有线段投影到一条直线上,如果这些所有投影至少相交于一点就输出Yes!,否则输出No!。
解题思路:如果有存在这样的直线,过投影相交区域作直线的垂线,该垂线必定与每条线段相交,问题转化为问是否存在一条线和所有线段相交
若存在一条直线与所有线段相机相交,此时该直线必定经过这些线段的某两个端点,所以枚举任意两个端点即可。
这里要主要的地方就是,题目说如果两个点的距离小于1e-8就等价于一点,所以要考虑重点
/* Memory 200K Time 32MS */ #include <iostream> #include <math.h> using namespace std; #define MAXM 110 #define EPS 1e-8 typedef struct{ double x1,y1,x2,y2; }Segment; Segment segment[MAXM]; int n; double distance(double x1,double y1,double x2,double y2){ return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)); } double corss(double x1,double y1,double x2,double y2,double x,double y){ return (x2-x1)*(y-y1)-(x-x1)*(y2-y1); } bool judge(double x1,double y1,double x2,double y2){ int i; if(distance(x1,y1,x2,y2)<EPS) return 0; for(i=0;i<n;i++){ if(corss(x1,y1,x2,y2,segment[i].x1,segment[i].y1)* corss(x1,y1,x2,y2,segment[i].x2,segment[i].y2)>EPS) return 0; } return 1; } int main(){ int t,i,j,ans; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i=0;i<n;i++) scanf("%lf%lf%lf%lf",&segment[i].x1,&segment[i].y1,&segment[i].x2,&segment[i].y2); if(n==1) {printf("Yes!\n");continue;} ans=0; for(i=0;i<n && !ans;i++) for(j=i+1;j<n && !ans;j++){ if(judge(segment[i].x1,segment[i].y1,segment[j].x1,segment[j].y1) || judge(segment[i].x1,segment[i].y1,segment[j].x2,segment[j].y2) || judge(segment[i].x2,segment[i].y2,segment[j].x1,segment[j].y1) || judge(segment[i].x2,segment[i].y2,segment[j].x2,segment[j].y2)) ans=1; } if(ans) printf("Yes!\n"); else printf("No!\n"); } return 0;