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

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; i
       
       
         0)//同侧 { 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 
         
       
      
      
     
     
    
    
   
   




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值