您的位置:首页 > 其它

poj 3304 判断是否有与所有线段相交的直线

2014-07-24 21:09 393 查看
题意:已知平面上有n条线段,通过端点坐标给出。求当所有线段投影到一条直线上时,所有投影线段是否能够交于一点。能输出Yes!,否则输出No!。

思路(参考http://blog.csdn.net/wangjian8006/article/details/7893064):如果有存在这样的直线,过投影相交区域作直线的垂线,该垂线必定与每条线段相交,问题转化为问是否存在一条线和所有线段相交。若存在一条直线与所有线段相机相交,此时该直线必定经过这些线段的某两个端点,所以枚举任意两个端点即可。这里要注意的地方就是,题目说如果两个点的距离小于1e-8就等价于一点,所以要考虑重点。

#include <stdio.h>
#include <string.h>
#include <math.h>
#define ZERO 1e-8
struct podouble{
double x1,y1,x2,y2;
}p[104];
int n,T;
double distance(double x1,double y1,double x2,double y2){
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
double cross(double x1,double y1,double x2,double y2,double x,double y){
return (x2-x1)*(y-y1)-(x-x1)*(y2-y1);
}
double test(double x1,double y1,double x2,double y2){
int i;
if(distance(x1,y1,x2,y2) < ZERO)//两个点相距太近,视为重点
return 0;
for(i = 0;i<n;i++){
if(cross(x1,y1,x2,y2,p[i].x1,p[i].y1)*
cross(x1,y1,x2,y2,p[i].x2,p[i].y2) > ZERO)//存在线段与直线没有交点
return 0;
}
return 1;
}
double main(){
freopen("a.txt","r",stdin);
scanf("%d",&T);
while(T--){
int i,j,flag=0;
scanf("%d",&n);
for(i = 0;i<n;i++)
scanf("%lf %lf %lf %lf",&p[i].x1,&p[i].y1,&p[i].x2,&p[i].y2);
if(n==1)
flag = 1;
else{
for(i = 0;i<n-1&&!flag;i++)
for(j = i+1;j<n&&!flag;j++){
if(test(p[i].x1,p[i].y1,p[j].x1,p[j].y1)||
test(p[i].x1,p[i].y1,p[j].x2,p[j].y2)||
test(p[i].x2,p[i].y2,p[j].x1,p[j].y1)||
test(p[i].x2,p[i].y2,p[j].x2,p[j].y2))
flag = 1;
}
}
if(flag)
printf("Yes!\n");
else
printf("No!\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: