想看更多的解题报告: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;