您的位置:首页 > 其它

POJ3304 计算几何--判断直线与线段相交

2017-09-27 18:48 591 查看
POJ3304 题意“:给N个线段,如果N个线段能找到一条直线L ,使得N个线段在L上投影至少有一个公共点,输出YES,否则输出NO

思路:如果存在L的话,能说明什么。。说明L的法线L’肯定能经过所有的线段

若存在一条直线L‘能经过所有线段,说明存在L’经过所有线段的两个端点

那么我们只要枚举两个端点P1P2,对每个直线P1P2 遍历所有线段i:1~N,用外积<=0来判断线段的两个端点L1L2是否在P1P2的两侧,如果找到一组P1P2就能输出YES了

(L1P1^L1P2 )*(L2P1^L2P2 )<0        ^代表外积,如下图



注意:要判断重复点,即P1P2有可能重点,那么只要加判一下就好了

代码如下:

#include
#include
#include
#include
typedef long long int ll;
using   namespace    std;
const double eps = 1e-8;
const double PI = acos(-1.0);
int sgn(double x)
{
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
struct point
{
double x,y;
point() {}  point(double _x,double _y)
{
x = _x;
y = _y;
}  point operator -(const point &b)const
{
return point(x - b.x,y - b.y);

}
double operator ^(const point &b)const	//叉积
{
return x*b.y - y*b.x;
}
double operator *(const point &b)const //点积
{
return x*b.x + y*b.y;     //绕原点旋转角度B(弧度值),后x,y的变化
}
void transXY(double B)
{
double tx = x,ty = y;
x = tx*cos(B) - ty*sin(B);
y = tx*sin(B) + ty*cos(B);
}
}points[1005];
struct line
{
point s,e;
line() {}
line(point _s,point _e)
{
s = _s;
e = _e;
}
} lines[1005];
double xmult(point p0,point p1,point p2) //计算p0p1 X p0p2
{
return (p1-p0)^(p2-p0);
}
bool check(line a,int n)
{
if(sgn(a.s.x-a.e.x)==0&&sgn(a.s.y-a.e.y)==0)//重复点
return false;
int flag=0;
for(int i=0; i0)//同侧
{
return false;
}
}
return true;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
int num=0;
for(int i=0; i>t1>>t2>>t3>>t4;
points[num++]=point(t1,t2);
points[num++]=point(t3,t4);
lines[i].s=point(t1,t2);
lines[i].e=point(t3,t4);
}
int flag=0;
if(n<3)
flag=1;
for(int i=0; i<num; i++)
{
for(int j=i+1; j<num; j++)
{
line lt1=line(points[i],points[j]);
if(check(lt1,n))
{
//	cout<<lt1.s.x<<" "<<lt1.s.y<<" "<<i<<" "<<j<<" "<<endl;
//	cout<<lt1.e.x<<" "<<lt1.e.y<<" "<<i<<" "<<j<<" "<<endl;
flag=1;
break;
}
}
if(flag)
break;
}
if(flag)
printf("Yes!\n");
else
printf("No!\n");
}

}sssssss
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: