poj3304 - Segments

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


 

你可能感兴趣的:(struct,ini,ansj,distance)